//
// Copyright 2003, Juan Segarra Flor
//
// This is part of videocache
//
// Videocache is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// Videocache is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Foobar; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//

#include "bwtable.h"

#ifdef SENDALGORITHM
// implementations of adjustthisslot depending on the used policy
/*
#if SENDALGORITHM == ALLPROPORTIONAL
int bwtable::adjustthisslot(int numslot) {
  long *slot,*ids=NULL,*idsaux=NULL,maxbw,streamremainingbw;//,maxbwsent=0;
  int contvid,numlink;
  t_plan *plan;//, *auxplan;
  int numids=0,contids;
  char adjustflag;
  unsigned long totalbwplanned; // warning, may cause overflow
  double proportionalbw,totalprop=0;//cummumaxbw=0;
  //t_timeslot *actual;
  long initialavailablebw,notusedyet,availablebw;
  int advancements=0;

  slot=seekslot(numslot);
  if (slot==NULL) {
    cerr<<"adjustthisslot: Slot does not exist ?¿?"<<endl;
    exit(-2);
  }
  for (numlink=0;numlink<maxlinks;numlink++) {
    if (capacity[numlink]<slot[numlink]) {
      cerr<<"adjustthisslot: detected overused link "<<numlink<<endl;
      exit(-2);
    }
    // mirar el bw que sobra (esta dalt del switch)
    // contar bw total que falta per transmetre per eixe link
    totalbwplanned=getplannedbwfromslot(numslot);
    initialavailablebw=capacity[numlink]-slot[numlink];
    notusedyet=0;
    // asignar el bw que sobra amb la proporcio de bw que necessita cada
    //   stream respecte del total a transmetre
    contvid=maxvideos;
    while ((capacity[numlink]>slot[numlink])&&(contvid>0)) {
      plan=planlistbyvid[contvid-1];
      numids=0;
      free(ids);
      ids=NULL;// needed to be null for avoiding freeing a not null ptr
      free(idsaux);
      idsaux=NULL;
      while (plan!=NULL) {
	adjustflag=1;
	contids=0;
	while ((contids<numids)&&(adjustflag)) {
	  if (ids[contids]==plan->id)
	    adjustflag=0;
	  contids++;
	}
	if (adjustflag) {
	  if (numids%10==0) { // increase in steps of 10
	    free(idsaux);
	    idsaux=ids;
	    ids=(long*)calloc(numids+10,sizeof(long));
	    if (ids==NULL) {
	      cerr<<"adjustthisslot: not enough memory for IDs"<<endl;
	      exit(-1);
	    }
	    memcpy(ids,idsaux,numids*sizeof(long));
	  }
	  ids[numids]=plan->id;
	  numids++;
	  
	  streamremainingbw=getvideoplannedbwfromslot(contvid-1,numslot);
	  if (streamremainingbw>MAXDISKBW)
	    streamremainingbw=MAXDISKBW;
	  
	  if (totalbwplanned==0) // if there is nothing planned, use all bw
	    maxbw=MAXDISKBW;
	  else {
	    proportionalbw=(double)(streamremainingbw)/totalbwplanned;
	    maxbw=(long)(initialavailablebw*proportionalbw);
	    maxbw+=notusedyet; // bw not used but already tested
	    if (maxbw>MAXDISKBW)
	      maxbw=MAXDISKBW;
	    if (plan->id==ids[0]){
	      totalprop+=proportionalbw;
	    }
	  }
	  availablebw=capacity[numlink]-slot[numlink];
	  advancements+=adjusttransmplan(contvid,plan->id,maxbw,numslot,numlink);
	  notusedyet+=maxbw-(availablebw-(capacity[numlink]-slot[numlink]));
	  // probably plan is now an invalid pointer, we have
	  // to restart from the first plan of this video
	  plan=planlistbyvid[contvid-1];
	}
	else
	  plan=plan->next;
      }
      contvid--;
    }
    totalprop=0;
  }
#ifdef SHOWADVANCEMENTS
  cout<<">>adv in "<<numslot<<": "<<advancements<<endl;
#endif
  return 1;
}
#endif
*/

// best policy
int bwtable::adjustthisslot(int numslot) {
  int contvid;
  t_plan *plan;
  int advancements=0;

#if SENDALGORITHM == UNPOPULARFIRST
  contvid=maxvideos;
  while (contvid>0) {
    plan=planlistbyvid[contvid-1];
    if (plan!=NULL)    
      advancements+=adjusttransmplan(contvid,numslot);
    contvid--;
  }
#elif SENDALGORITHM == POPULARFIRST
  contvid=1;
  while (contvid<=maxvideos) {
    plan=planlistbyvid[contvid-1];
    if (plan!=NULL)    
      advancements+=adjusttransmplan(contvid,numslot);
    contvid++;
  }
#endif

#ifdef SHOWADVANCEMENTS
  cout<<">>adv in "<<numslot<<": "<<advancements<<endl;
#endif
  return 1;
}
#endif


long bwtable::getplannedbwfromslot(int numslot) {
   t_plan *plan;
   int contvid;
   long totalvideobw=0,totalbw=0;

   for (contvid=0;contvid<maxvideos;contvid++) {
     plan=planlistbyvid[contvid];
     // calculate current video bw usage
     totalvideobw=0;
     while ((plan!=NULL)&&(totalvideobw<MAXDISKBW)) {
       //if (isinlinks(numlink,plan) && (plan->start+plan->duration>numslot)) {
       if (plan->start+plan->duration>numslot) {
	 totalvideobw+=plan->bw;
       }
       plan=plan->next;
     }
     if (totalvideobw>MAXDISKBW)
       totalbw+=MAXDISKBW;
     else
       totalbw+=totalvideobw;
   }
   return totalbw;
}
long bwtable::getvideoplannedbwfromslot(int videoid,int numslot) {
  t_plan *plan;
  long totalvideobw;

  plan=planlistbyvid[videoid];
  totalvideobw=0;
  while (plan!=NULL) {
    if (plan->start+plan->duration>numslot) {
      totalvideobw+=plan->bw;
    }
    plan=plan->next;
  }
  return totalvideobw;
}


int bwtable::adjusttransmplan(int video,int numslot) {
  const int maxitems=1000;
  t_plan *orderedlist[maxitems],*plan;
  int lastitem,contitem,cont2,advancements=0;

  //cerr<<"processing advancements (slot "<<numslot<<", current slot "<<actualslot<<")... "<<flush;
  if (video<1 || video>maxvideos) {
    cerr<<"adjusttransmplan: trying to get video "<<video<<" (there are "<<maxvideos<<")"<<endl;
    exit(-2);
  }

#if PARTSENDALGORITHM == FIRSTPARTSFIRST
  // make an ordered by starttime plan list
  plan=planlistbyvid[video-1];
  while ((plan->next!=NULL)&&(plan->start<=numslot)) 
    plan=plan->next;
  if (plan->start>numslot) {
    orderedlist[0]=plan;
    plan=plan->next;
    lastitem=1;
  }
  else {
    plan=NULL;
    lastitem=0;
  }
  while (plan!=NULL){
    if (plan->start>numslot) {
      contitem=0;
      while (contitem<lastitem) {
	if ((plan->start<orderedlist[contitem]->start)&&
	    (plan->start>numslot)) {
	  for (cont2=lastitem;cont2>contitem;cont2--)
	    orderedlist[cont2]=orderedlist[cont2-1];
	  orderedlist[contitem]=plan;
	  lastitem++;
	  if (lastitem>=maxitems) {
	    cerr<<"adjusttransmplan: too few space in static list "<<endl;
	    exit(-2);
	  }
	  contitem=lastitem; // to exit the loop
	}
	contitem++;
      }
    }
    plan=plan->next;
  }
#else
#error defined PARTSENDALGORITHM not implemented
#endif
  //cerr<<"plans suitable to advance: "<<lastitem<<endl;
  contitem=0;
  while (contitem<lastitem) {
    if (isinids(-1,orderedlist[contitem])==0){
      if (adjustthisplan(video,orderedlist[contitem],numslot)) {
	advancements++;
      }
    }
    contitem++;
  }
  //cerr<<"ok"<<endl;
  return advancements;
}


// adjusts a video plan
// if id=-1, adjust all plans of the videoid
/*
int bwtable::adjusttransmplan(int video,long id,long maxbw,
			      int numslot,int numlink) {
  t_plan *plan,*nextplan;
  long currentvideobw,totalvideobw,planbw;
  int remainingparts,numpart;
  double currratio;
  int *slotlist,contslots;//numslots,;
  int advancements=0;

  // calculate video information
  if (video<1 || video>maxvideos) {
    cerr<<"adjusttransmplan: trying to get video "<<video<<" (there are "<<maxvideos<<")"<<endl;
    exit(-2);
  }
  plan=planlistbyvid[video-1];
  currentvideobw=0; // video bw planned in this slot
  totalvideobw=0;   // total planned video bw 
  remainingparts=0; // video parts remaining for transmission 
  while (plan!=NULL) {
    if (plan->start+plan->duration>numslot) {
      if (plan->start<=numslot)
	currentvideobw+=plan->bw;
      else
	remainingparts++;
      totalvideobw+=plan->bw;
    }
    plan=plan->next;
  }

  // make adjustments
  plan=planlistbyvid[video-1];
  switch (PARTSENDALGORITHM) {
  case BALANCETRANSM: {
    // ********************* BALANCE PARTS *****************************
    numpart=1;
    currratio=(double)totalvideobw/(double)maxbw;
    while (plan!=NULL) {
      nextplan=plan->next;
      planbw=plan->bw;
      if (((plan->id==id)||(id==-1))&&
	  ((plan->start>numslot)&&(numpart>=currratio))) {
	if (plan->bw+currentvideobw<=maxbw) {
	  // adjust the sending ratio
	  currratio+=(double)totalvideobw/(double)maxbw;
	  if (adjustthisplan(video,id,plan,numslot)) {
	    currentvideobw+=planbw;
	    advancements++;
	  }
	}
      }
      plan=nextplan;
      numpart++;
    }
    break;
  }
  case BALANCELINKS: {
    // ********************* BALANCE LINKS *****************************
    slotlist=getbwusage(video,numlink,numslot);
    contslots=0;
    while (slotlist[contslots]!=-1) {
      plan=planlistbyvid[video-1];
      while (plan!=NULL) {
	nextplan=plan->next;
	planbw=plan->bw;
	if ((plan->start==slotlist[contslots]) &&
	    (plan->bw+currentvideobw<=maxbw)) {
	  if (adjustthisplan(video,id,plan,numslot)) {
	    currentvideobw+=planbw;
	    advancements++;
	  }
	}
	plan=nextplan;
      }
      contslots++;
    }
    free(slotlist);
    break;
  }
  case FIRSTPARTSFIRST: {
    plan=getplanbytime(video,numslot);
    while (plan!=NULL) {
      planbw=plan->bw;
      if ((plan->bw+currentvideobw<=maxbw) && 
	  (adjustthisplan(video,id,plan,numslot))) {
	  currentvideobw+=planbw;
	  advancements++;
	  plan=getplanbytime(video,numslot);
      }
      else
	plan=NULL;
    }
    break;
  }
  case LATESTPARTSFIRST: {
    plan=getplanbyinvtime(video,numslot);
    while (plan!=NULL) {
      planbw=plan->bw;
      if ((plan->bw+currentvideobw<=maxbw) && 
	  (adjustthisplan(video,id,plan,numslot))) {
	  currentvideobw+=planbw;
	  advancements++;
	  plan=getplanbyinvtime(video,numslot);
      }
      else
	plan=NULL;
    }
    break;
  }
  default: {
    cerr<<"Part sending policy for dynamic adjustments not selected"<<endl;
    exit(-2);
    break;
  }}
  return advancements;
}
*/

// test a new slot for a plan and changes it if possible
int bwtable::adjustthisplan(int video,t_plan *plan,int numslot) {
  int planpart,plandur,contlinks;
  long planbw;
  int *planlinklist,*auxplanlinklist;
  long *planidlist;
  int accepted=1,contids;
  
  contids=0;
  while ((accepted)&&(plan->idlist[contids]!=-2)) {
    //cerr<<"testing for id "<<plan->idlist[contids]<<"... "<<flush;
    if ((plan->idlist[contids]==-1)||(testroute(video,plan->part,plan->bw,numslot,plan->duration,plan->linklist,plan->idlist[contids])==0)) {
      accepted=0;
      //cerr<<" accepted"<<endl;
    }
    //else
    //cerr<<" rejected"<<endl;
    contids++;
  }
  if (accepted) {
    // make a copy of the plan
    planpart=plan->part;
    planbw=plan->bw;
    plandur=plan->duration;
    contlinks=0;
    while (plan->linklist[contlinks]!=-1)
      contlinks++;
    planlinklist=(int*)calloc(contlinks+1,sizeof(int));
    auxplanlinklist=(int*)calloc(contlinks+1,sizeof(int));
    if ((planlinklist==NULL)||(auxplanlinklist==NULL)) {
      cerr<<"adjustthisplan: not enough memory for planlinklist"<<endl;
      exit(-1);
    }
    memcpy(planlinklist,plan->linklist,(contlinks+1)*sizeof(int));
    planidlist=(long*)calloc(contids+1,sizeof(long));
    if (planidlist==NULL) {
      cerr<<"adjustthisplan: not enough memory for planidlist"<<endl;
      exit(-1);
    }
    memcpy(planidlist,plan->idlist,(contids+1)*sizeof(long));
    // change plan
    unreserveplan(video,plan);
    contids=0;
    while ((accepted)&&(planidlist[contids]!=-2)) {
      //cerr<<"reall v"<<video<<" p"<<planpart<<" bw"<<planbw<<" slt"<<numslot<<" dur"<<plandur<<" usr"<<planidlist[contids]<<endl;
      memcpy(auxplanlinklist,planlinklist,(contlinks+1)*sizeof(int));
      accepted=reserveroute(video,planpart,planbw,numslot,
			    plandur,auxplanlinklist,planidlist[contids]);
      contids++;
    }
    free(planlinklist);
    free(planidlist);
    if (accepted==0) {
      cerr<<"adjustthisplan: error: route could not be reserved"<<endl;
      exit(-2);
    }
  }
  return accepted;
}

// returns a plan using the most saturated slot in link
// the returned plan has less bandwidth requirements than maxbw
// if video or id are not -1, the returned plan must be of that video/id
// if video==-1, id is ignored
/*
t_plan* bwtable::getplanbylinkusage(long numlink,int video,long id,long maxbw) {
  t_timeslot* mostsaturated;
  t_plan* planlist;
  int numvid;

  mostsaturated=getmostsaturatedslot(numlink,video,id);
  if (mostsaturated==NULL) {
    cerr<<"warning: getplanbylinkusage: no video found using the selected link "
	<<numlink<<endl;
  }
  else {
    if (video==-1) {
      numvid=0;
      while (numvid<maxvideos) {
	planlist=planlistbyvid[numvid];
	while (planlist!=NULL) {
	  if (isinlinks(numlink,planlist) && planlist->bw<=maxbw)
	    return planlist;
	  planlist=planlist->next;
	}
	numvid++;
      }
      cerr<<"warning: not found any video-part using the selected link ("
	  <<numlink<<") with less bw than "<<maxbw<<endl;
      //exit(-2);
    }
    else if (id==-1) {
      planlist=planlistbyvid[video-1];
      while (planlist!=NULL) {
	if (isinlinks(numlink,planlist) && planlist->bw<=maxbw)
	  return planlist;
	planlist=planlist->next;
      }
      cerr<<"warning: not found any video-part of video "
	  <<video<<" using the selected link ("
	  <<numlink<<") with less bw than "<<maxbw<<endl;
      //exit(-2);
    }
    else {
      planlist=planlistbyvid[video-1];
      while (planlist!=NULL) {
	if (planlist->id==id && isinlinks(numlink,planlist) && planlist->bw<=maxbw)
	  return planlist;
	planlist=planlist->next;
      }
      cerr<<"warning: not found any video-part of video "
	  <<video<<" with id "<<id<<" using the selected link ("
	  <<numlink<<") with less bw than "<<maxbw<<endl;
      //exit(-2);
    }
  }
  return NULL;
}
*/

// returns the most saturated slot used by video and id
// if id==-1, it is not considered
// if video==-1, video and id are not considered
/*
t_timeslot* bwtable::getmostsaturatedslot(long numlink,int video,long id){
  t_timeslot* actual=first,*result=NULL;
  t_plan* planlist;
  long mostsaturation=0;

  if (numlink>=maxlinks) {
    cerr<<"getmostsaturatedslot: Trying to seek an unexistend link ("
	<<numlink<<"), there are "<<maxlinks<<endl;
    exit(-2);
  }
  if (video==0 || video<-1 || video>maxvideos) {
    cerr<<"getmostsaturatedslot: Trying to seek an unexistend video ("
	<<video<<"), there are "<<maxvideos<<endl;
    exit(-2);
  }
  
  while (actual!=NULL) {
    if (video==-1) {
      if (actual->link[numlink]>mostsaturation) {
	mostsaturation=actual->link[numlink];
	result=actual;
      }
    }
    else if (id==-1) {
      planlist=planlistbyvid[video-1];
      while (planlist!=NULL) {
	if (isinlinks(numlink,planlist))
	  if (actual->link[numlink]>mostsaturation) {
	    mostsaturation=actual->link[numlink];
	    result=actual;
	  }
	planlist=planlist->next;
      }
    }
    else {
      planlist=planlistbyvid[video-1];
      while (planlist!=NULL) {
	if (planlist->id==id && isinlinks(numlink,planlist))
	  if (actual->link[numlink]>mostsaturation) {
	    mostsaturation=actual->link[numlink];
	    result=actual;
	  }
	planlist=planlist->next;
      }
    }
    actual=actual->next;
  }
  return result;
}
*/

// returns the first plan in time planned after numslot
t_plan* bwtable::getplanbytime(int video,int numslot) {
  t_plan* plan,*firstplan=NULL;
  int firststart=-1;

  if (video<1 || video>maxvideos) {
    cerr<<"getplanbytime: trying to get video "<<video<<" (there are "<<maxvideos<<")"<<endl;
    exit(-2);
  }
  plan=planlistbyvid[video-1];
  while (plan!=NULL){
    if (plan->start>numslot) {
      if ((firststart==-1)||(plan->start<firststart)) {
	firststart=plan->start;
	firstplan=plan;
      }
    }
    plan=plan->next;
  }
  return firstplan;
}
// returns the last plan in time planned after numslot
t_plan* bwtable::getplanbyinvtime(int video,int numslot) {
  t_plan* plan,*lastplan=NULL;
  int laststart=-1;

  if (video<1 || video>maxvideos) {
    cerr<<"getplanbyinvtime: trying to get video "<<video<<" (there are "<<maxvideos<<")"<<endl;
    exit(-2);
  }
  plan=planlistbyvid[video-1];
  while (plan!=NULL){
    if (plan->start>numslot) {
      if ((laststart==-1)||(plan->start>laststart)) {
	laststart=plan->start;
	lastplan=plan;
      }
    }
    plan=plan->next;
  }
  return lastplan;
}
 
// returns an array of slot numbers ordered by bw used
// slot numbers include only those used by video (the firsts of each part)
int* bwtable::getbwusage(int video,int link,int numslot) {
  t_plan* plan;
  int numparts=0,*slotlist,contparts,contslot,auxslot,thisplan;
  long *slot,*bwlist,maxbw,auxbw;

  // count the array size
  if (video<1 || video>maxvideos) {
    cerr<<"getbwusage trying to get video "<<video<<" (there are "<<maxvideos<<")"<<endl;
    exit(-2);
  }
  plan=planlistbyvid[video-1];
  while (plan!=NULL){
    if (plan->start>numslot)
      numparts++;
    plan=plan->next;
  }
  slotlist=(int*)calloc(numparts+1,sizeof(int));
  if (slotlist==NULL) {
    cerr<<"getbwusage: not enough memory for slotlist"<<endl;
    exit(-1);
  }
  bwlist=(long*)calloc(numparts+1,sizeof(long));
  if (bwlist==NULL) {
    cerr<<"getbwusage: not enough memory for bwlist"<<endl;
    exit(-1);
  }
  for (contparts=0;contparts<(numparts+1);contparts++) {
    slotlist[contparts]=-1;
    bwlist[contparts]=-1;
  }
  plan=planlistbyvid[video-1];
  while (plan!=NULL){
    if (plan->start>numslot) {
      maxbw=-1;
      for (contslot=plan->start;contslot<(plan->start+plan->duration);contslot++) {
	slot=seekslot(contslot);
	if (slot==NULL) {
	  cerr<<"getbwusage: unexistent slot"<<endl;
	  exit(-2);
	}
	if (slot[link]>maxbw)
	  maxbw=slot[link];
      }
      contparts=0;
      thisplan=plan->start;
      while (maxbw!=-1) {
	while (maxbw<bwlist[contparts])
	  contparts++;
	auxbw=bwlist[contparts];
	auxslot=slotlist[contparts];
	bwlist[contparts]=maxbw;
	slotlist[contparts]=thisplan;
	maxbw=auxbw;
	thisplan=auxslot;
	contparts++;
      }
    }
    plan=plan->next;
  }
  free(bwlist);
  return slotlist;
}
  

// returns the link capacity
long bwtable::getlinkcapacity(int link) {
  if (link>=0 && link<maxlinks)
    return capacity[link];
  else {
    cerr<<"getlinkcapacity: link "<<link<<" does not exist"<<endl;
    exit(-2);
  }
}

// returns the first starting slot or -1 if it's not planned
/*
int bwtable::getfirsttranstime(int video) {
  t_plan *aux,*firsttrans=NULL;

  aux=planlistbyvid[video-1];
  while (aux!=NULL) {
    if ((aux->part==0)&&(aux->start>=actualslot)) //found 
      if (firsttrans==NULL)
	firsttrans=aux;
      else {
	if (firsttrans->start>aux->start)
	  firsttrans=aux;
      }
    aux=aux->next;
  }
  if (firsttrans!=NULL)
    return firsttrans->start;
  else
    return -1;
}
*/

// returns if mylink is in links of plan
int bwtable::isinlinks(int mylink,t_plan *plan) {
  int c1=0;

  if (plan!=NULL)
    while (plan->linklist[c1]!=-1) {
      if (mylink==plan->linklist[c1])
	return 1;
      c1++;
    }
  return 0;
}
// returns if myid is in ids of plan
int bwtable::isinids(long myid,t_plan *plan) {
  int c1=0;

  if (plan!=NULL)
    while (plan->idlist[c1]!=-2) {
      if (myid==plan->idlist[c1])
	return 1;
      c1++;
    }
  return 0;
}



// returns the BEST plan to try to add a multicast, or NULL
//// returns the LAST plan in time if exists, or NULL
// stricflag==-1 means a plan in the exact timeslot (reallocations)
// even with streammerging
/*
t_plan* bwtable::seekplan(int video,int part,int startslot,
			  long strictflag) {
  t_plan *aux=planlistbyvid[video-1];

  while (aux!=NULL) {
#ifdef STREAMMERGING
    if ((strictflag==-1 && aux->plan==part && aux->start==startslot)||
	(aux->part==part && aux->start<=startslot && aux->start>=actualslot))
#else
    if (aux->part==part && aux->start==startslot)
#endif
      return aux;
    else
      aux=aux->next;
  }
  return NULL;
}
*/
// returns the BEST plan to try to add a multicast, or NULL
// (in a bus, the only one possible would be the last one, but
// in a tree maybe not)
// stricflag==-1 means a plan in the exact timeslot (reallocations)
// even with streammerging
t_plan* bwtable::seekplan(int video,int part,int startslot,
			  long strictflag,int*linklist) {
  t_plan *aux=planlistbyvid[video-1];
  int contlink;

  while (aux!=NULL) {
#ifdef STREAMMERGING
    if ((strictflag==-1 && aux->part==part && aux->start==startslot)||
	(aux->part==part && aux->start<=startslot && aux->start>=actualslot)) {
#else
    if (aux->part==part && aux->start==startslot){
#endif
      contlink=0;
      while (linklist[contlink]!=-1) {
	if (isinlinks(linklist[contlink],aux))
	  return aux;
	contlink++;
      }
    }
    aux=aux->next;
  }
  return NULL;
}
t_plan* bwtable::seekplantoremove(int video,int part,long user) {
  t_plan *aux=planlistbyvid[video-1];
  
  while (aux!=NULL) {
    if ((aux->part==part)&&(isinids(user,aux))) 
      return aux;
    aux=aux->next;
  }
  return NULL;
}

// adds a link to a multicast transmission
int bwtable::addmulticastplan(int mylink,long myid,t_plan *plan) {
  int *newlinklist,numlinks;

  if (plan==NULL) {
    cerr<<"addmulticastplan: invalid plan"<<endl;
    exit(-2);
  }
  if (isinlinks(mylink,plan)==0) {
    // add the new link
    numlinks=0;
    while (plan->linklist[numlinks]!=-1)
      numlinks++;
    newlinklist=(int*)calloc(numlinks+2,sizeof(int));
    if (newlinklist==NULL) {
      cerr<<"addmulticastplan: not enough memory"<<endl;
      exit(-1);
    }
    memcpy(newlinklist,plan->linklist,numlinks*sizeof(int));
    newlinklist[numlinks]=mylink;
    newlinklist[numlinks+1]=-1;
    free(plan->linklist);
    plan->linklist=newlinklist;
  }
  addid(myid,plan);
  return 1;
}
int bwtable::removeid(long id,t_plan* plan) {
  int numids,found=0;
  long* newidlist;

  if (isinids(id,plan)) {
    numids=0;
    while (plan->idlist[numids]!=-2){
      if (plan->idlist[numids]==id)
	found=1;
      else if (found)
	plan->idlist[numids-1]=plan->idlist[numids];
      numids++;
    }
    newidlist=(long*)calloc(numids,sizeof(long));
    if (newidlist==NULL) {
      cerr<<"removeid: not enough memory"<<endl;
      exit(-1);
    }
    memcpy(newidlist,plan->idlist,(numids-1)*sizeof(long));
    newidlist[numids-1]=-2;
    free(plan->idlist);
    plan->idlist=newidlist;
  }
  return 1;
}
int bwtable::addid(long myid,t_plan* plan) {
  int numids;
  long* newidlist;

  if (isinids(myid,plan)==0) {
    // add the new id
    numids=0;
    while (plan->idlist[numids]!=-2)
      numids++;
    newidlist=(long*)calloc(numids+2,sizeof(long));
    if (newidlist==NULL) {
      cerr<<"addmulticastplan: not enough memory"<<endl;
      exit(-1);
    }
    memcpy(newidlist,plan->idlist,numids*sizeof(long));
    newidlist[numids]=myid;
    newidlist[numids+1]=-2;
    free(plan->idlist);
    plan->idlist=newidlist;
  }
  return 1;
}
int bwtable::removelink(int link,t_plan* plan) {
  int numlinks,found=0;
  int* newlinklist;

  if (isinlinks(link,plan)) {
    numlinks=0;
    while (plan->linklist[numlinks]!=-1){
      if (plan->linklist[numlinks]==link)
	found=1;
      else if (found)
	plan->linklist[numlinks-1]=plan->linklist[numlinks];
      numlinks++;
    }
    newlinklist=(int*)calloc(numlinks,sizeof(int));
    if (newlinklist==NULL) {
      cerr<<"removelink: not enough memory"<<endl;
      exit(-1);
    }
    memcpy(newlinklist,plan->linklist,(numlinks-1)*sizeof(int));
    newlinklist[numlinks-1]=-1;
    free(plan->linklist);
    plan->linklist=newlinklist;
  }
  return 1;
}
 
// adds a new transmission plan
int bwtable::addplan(int video,int part,int startslot,int* linklist,
		     int duration,long bw,long id) {
  t_plan *aux;
  int numlinks;

  aux=new(t_plan);
  if (aux==NULL) {
    cerr<<"addplan: Not enough memory for creating plan"<<endl;
    exit(-1);
  }
  aux->part=part;
  aux->start=startslot;
  numlinks=0;
  while (linklist[numlinks]!=-1)
    numlinks++;
  aux->linklist=(int*)calloc(numlinks+1,sizeof(int));
  if (aux->linklist==NULL) {
    cerr<<"addplan: Not enough memory for creating plan link list"<<endl;
    exit(-1);
  }
  memcpy(aux->linklist,linklist,numlinks*sizeof(int));
  aux->linklist[numlinks]=-1;
  aux->idlist=(long*)calloc(2,sizeof(long));
  if (aux->idlist==NULL) {
    cerr<<"addplan: Not enough memory for creating plan id list"<<endl;
    exit(-1);
  }
  aux->idlist[0]=id;
  aux->idlist[1]=-2;
  aux->duration=duration;
  aux->bw=bw;
  aux->prev=NULL;
  if (planlistbyvid[video-1]!=NULL)
    planlistbyvid[video-1]->prev=aux;
  aux->next=planlistbyvid[video-1];
  planlistbyvid[video-1]=aux;
  return 1;
}


int bwtable::delplan(t_plan *aux,int videolist) {
  if (aux==NULL) {
    cerr<<"delplan: Trying to delete an unexistent plan"<<endl;
    exit(-2);
  }
  else {
    if (aux->prev!=NULL) 
      aux->prev->next=aux->next;
    else {
      planlistbyvid[videolist]=aux->next;
    }
    if (aux->next!=NULL)
      aux->next->prev=aux->prev;
    free(aux->linklist);
    free(aux->idlist);
    delete(aux);
    return 1;
  }
}  

// returns if a route can be reserved
/*
int bwtable::testroute(int video,int part,long bw,int startslot,
		       int duration,int* linklist,long id) {
  int accepted=2;
  int myslot,c1=0;
  t_plan* auxplan;

  if (linklist[0]==-1) {
    cerr<<"testroute: trying to test an empty route"<<endl;
    exit(-2);
  }
  while ((accepted)&&(linklist[c1]!=-1)) {
    // test if we can do a multicast
#ifdef MULTICAST
    auxplan=seekplan(video,part,startslot,id,linklist);
    if (auxplan==NULL || isinlinks(linklist[c1],auxplan)==0) {
#endif
      myslot=startslot;
      while ((accepted)&&(myslot<(startslot+duration))) {
	if (testslot(bw,myslot,linklist[c1])==0)
	  accepted=0;
	else
	  myslot++;
      }
#ifdef MULTICAST
    }
#endif
    c1++;
  }
  return accepted;
}
*/

// returns if a route can be reserved
int bwtable::testroute(int video,int part,long bw,int startslot,
		       int duration,int* linklist,long id) {
  t_plan* auxplan;
  int accepted=1,contlinks,myslot;

  if (linklist[0]==-1) {
    cerr<<"testroute: trying to test an empty route (user "<<id<<")"<<endl;
    exit(-2);
  }
#ifdef MULTICAST
  auxplan=seekplan(video,part,startslot,id,linklist);
#else
  auxplan=NULL;
#endif
  if (auxplan!=NULL) { // test a multicast transmission
    myslot=auxplan->start;
    while ((accepted)&&(myslot<(auxplan->start+duration))) {
      accepted=testuserslot(bw,myslot,id); // test userlink
      contlinks=0;
      while ((accepted)&&(linklist[contlinks]!=-1)) {
	if (isinlinks(linklist[contlinks],auxplan)==0)
	  accepted=testslot(bw,myslot,linklist[contlinks]);
	contlinks++;
      }
      myslot++;
    }
    //if (accepted) cerr<<"acc mcast"<<endl; else cerr<<"rej mcast"<<endl;
    if (accepted) // using multicast
      return accepted;
  }
  // test a new transmission plan
  accepted=1;
  myslot=startslot;
  while ((accepted)&&(myslot<(startslot+duration))) {
    accepted=testuserslot(bw,myslot,id); // test userlink
    contlinks=0;
    while ((accepted)&&(linklist[contlinks]!=-1)) {
      accepted=testslot(bw,myslot,linklist[contlinks]);
      contlinks++;
    }
    myslot++;
  }
  //if (accepted) cerr<<"acc unicast"<<endl; else cerr<<"rej unicast"<<endl;
  return accepted;
}

// modifies linklist to return added links
int bwtable::reserveroute(int video,int part,long bw,int startslot,
		       int duration,int* linklist,long id) {
  t_plan* auxplan;
  int accepted=1,contlinks,myslot,idadded=0;

  if (linklist[0]==-1) {
    cerr<<"reserveroute: trying to test an empty route"<<endl;
    exit(-2);
  }
  //cerr<<"v "<<video<<", p "<<part<<endl;
#ifdef MULTICAST
  auxplan=seekplan(video,part,startslot,id,linklist);
#else
  auxplan=NULL;
#endif
  if (auxplan!=NULL) { // test a multicast transmission
    //cerr<<"mcast"<<endl;
    myslot=auxplan->start;
    while ((accepted)&&(myslot<(auxplan->start+duration))) {
      if (isinids(id,auxplan)==0)
	accepted=testuserslot(bw,myslot,id); // test userlink
      else {
	cerr<<"reserveroute: re-reserving a plan?? (v "<<video<<" p "<<part<<")"<<endl;
	exit(-2);
      }
      contlinks=0;
      while ((accepted)&&(linklist[contlinks]!=-1)) { // test links
	if (isinlinks(linklist[contlinks],auxplan)==0)
	  accepted=testslot(bw,myslot,linklist[contlinks]);
	contlinks++;
      }
      myslot++;
    }
    if (accepted) {// using multicast
      //cerr<<" mcast resv (plan start "<<auxplan->start<<")"<<endl;
      // bandwidth reservation
      myslot=auxplan->start;
      while ((accepted)&&(myslot<(auxplan->start+duration))) {
	accepted=reserveuserslot(bw,myslot,id);
	contlinks=0;
	while ((accepted)&&(linklist[contlinks]!=-1)) {
	  if (isinlinks(linklist[contlinks],auxplan)==0)
	    accepted=reserveslot(bw,myslot,linklist[contlinks]);
	  contlinks++;
	}
	myslot++;
      }
      // planning information
      contlinks=0;
      while (linklist[contlinks]!=-1) {
	partstransmittedpp++;
	if (isinlinks(linklist[contlinks],auxplan)) {
	  partsmulticastpp++;
	  linklist[contlinks]=-2;
	}
	else {
	  addmulticastplan(linklist[contlinks],id,auxplan);// add link
	  idadded=1;
	}
	contlinks++;
      }
      if (!idadded)
	addid(id,auxplan);
      if (!accepted) {
	cerr<<"reserveroute: Trying to reserve more bandwidth than available to join a multicast"<<endl;
	exit(-2);
      }
      else
	return accepted;
    }
  }
  // test a new transmission plan
  //cerr<<" unicast "<<endl;
  accepted=1;
  myslot=startslot;
  while ((accepted)&&(myslot<(startslot+duration))) {
    accepted=reserveuserslot(bw,myslot,id);
    contlinks=0;
    while ((accepted)&&(linklist[contlinks]!=-1)) {
      partstransmittedpp++;
      accepted=reserveslot(bw,myslot,linklist[contlinks]);
      contlinks++;
    }
    myslot++;
  }
  if (accepted) {
    addplan(video,part,startslot,linklist,duration,bw,id);
    return accepted;
  }
  else {
    cerr<<"reserveroute: Cannot reserve route"<<endl;
    exit(-2);
  }
}


int bwtable::unreserveroute(int video,int part,long bw,int startslot,
			    int duration,int* linklist,long id) {
  t_plan* auxplan;
  int accepted=1,contlinks,myslot;

  auxplan=seekplantoremove(video,part,id);
  if (auxplan==NULL) {
    cerr<<"unreserveroute: trying to unreserve an unexistent route"<<endl;
    exit(-2);
  }
  if (auxplan->idlist[1]==-2) {// plan is only for this request
    //cerr<<"unreserving full plan"<<endl;
    unreserveplan(video,auxplan);
  }
  else { // plan is shared
    //cerr<<"unreserving mcast bandwidth"<<endl;
    myslot=auxplan->start;
    while ((accepted)&&(myslot<(auxplan->start+duration))) {
      accepted=unreserveuserslot(bw,myslot,id);
      contlinks=0;
      while ((accepted)&&(linklist[contlinks]!=-1)) {
	if (linklist[contlinks]!=-2)
	  accepted=unreserveslot(bw,myslot,linklist[contlinks]);
	contlinks++;
      }
      myslot++;
    }
    //cerr<<"unreserving mcast plan (user)"<<endl;
    removeid(id,auxplan);
    //cerr<<"unreserving mcast plan (links)"<<endl;
    contlinks=0;
    while (linklist[contlinks]!=-1) {
      partstransmittedpp--;
      if (linklist[contlinks]!=-2){
	removelink(linklist[contlinks],auxplan);
	partsmulticastpp--;
      }
      contlinks++;
    }
  }
  //cerr<<"done"<<endl;
  if (!accepted) {
    cerr<<"unreserveroute: Trying to unreserve more bandwidth than used"<<endl;
    exit(-2);
  }
  return accepted;
}

// returns if a route has been unreserved correctly
/* int bwtable::unreserveroute(int video,int part,int startslot) {
  t_plan *auxplan;
  char correct=1;
  int myslot,c1;

  auxplan=seekplan(video,part,startslot); //// MAL
  if (auxplan==NULL) {
    cerr<<"unreserveroute: trying to unreserve an unexistent route"<<endl;
    exit(-2);
  }
  c1=0;
  while ((correct)&&(auxplan->linklist[c1]!=-1)) {
    myslot=auxplan->start;
    while ((correct)&&(myslot<(auxplan->start+auxplan->duration))) {
      cerr<<"unreserv "<<auxplan->bw<<" in link "<<auxplan->linklist[c1]<<" in slot "<<myslot<<" by "<<video<<","<<part<<endl;
      correct=unreserveslot(auxplan->bw,myslot,auxplan->linklist[c1]);
      myslot++;
    }
    c1++;
  }
  if (correct)
    correct=delplan(auxplan,video-1);
  if (correct)
    return 1; 
  else {
    cerr<<"unreserveroute: error unreserving transmission"<<endl;
    exit(-2);
  }
  }*/

// returns if a plan has been unreserved correctly
int bwtable::unreserveplan(int video,t_plan* auxplan) {
  char correct=1;
  int myslot,c1;

  // is important not to call seekplan here, because it can get
  // another plan of the same video/part (not sure)
  if (auxplan==NULL) {
    cerr<<"unreserveplan: trying to unreserve an unexistent route"<<endl;
    exit(-2);
  }
  myslot=auxplan->start;
  while ((correct)&&(myslot<(auxplan->start+auxplan->duration))) {
    c1=0;
    while ((correct)&&(auxplan->linklist[c1]!=-1)) {
      correct=unreserveslot(auxplan->bw,myslot,auxplan->linklist[c1]);
      c1++;
    }
    c1=0;
    while ((correct)&&(auxplan->idlist[c1]!=-2)) {
      correct=unreserveuserslot(auxplan->bw,myslot,auxplan->idlist[c1]);
      c1++;
    }
    myslot++;
  }
  if (correct)
    correct=delplan(auxplan,video-1);
  if (correct)
    return 1; 
  else {
    cerr<<"unreserveplan: error unreserving transmission"<<endl;
    exit(-2);
  }
}

   
/* creates the bandwidth reservation table */
bwtable::bwtable(int numlinks,long linkcapacity,int numvideos,
		 long numusers,long userlinkcapacity) {
  int c1;

  cerr<<"Creating reservation table... "<<flush;
  first=NULL;
  maxlinks=numlinks;
  maxvideos=numvideos;
  maxusers=numusers;
  actualslot=0;
  planlistbyvid=(t_plan**)calloc(maxvideos,sizeof(t_plan*));
  if (planlistbyvid!=NULL) {
    for (c1=0;c1<maxvideos;c1++)
      planlistbyvid[c1]=NULL;
  }
  else {
    cerr<<"Not enough memory for plan table"<<endl;
    exit(-1);
  }
  capacity=(long*)calloc(maxlinks,sizeof(long));
  if (capacity!=NULL) {
    for (c1=0;c1<maxlinks;c1++) 
      capacity[c1]=linkcapacity;
  }
  else {
    cerr<<"Not enough memory for bwtable"<<endl;
    exit(-1);
  }
  usercapacity=(long*)calloc(maxusers,sizeof(long));
  if (usercapacity!=NULL) {
    for (c1=0;c1<maxusers;c1++)
      usercapacity[c1]=userlinkcapacity;
  }
  else {
    cerr<<"Not enough memory for bwtable"<<endl;
    exit(-1);
  }
  cerr<<"done"<<endl;
}

// returns the slot row
long* bwtable::seekslot(int numslot) {
  t_timeslot* actual=first,*aux,*prevactual=NULL;
  char found=0,searching=1;
  int c1;
  long contusers;

  if (actualslot>numslot) {
    cerr<<"seekslot: Trying to seek a past slot ("<<numslot
	<<"), actual is "<<actualslot<<endl;
    exit(-2);
    return NULL;
  }

  if (actual==NULL)
    searching=0;
  while (searching) {
    if (actual->slot==numslot) {
      found=1;
      searching=0;
    }
    else if (actual->slot>numslot) {
      searching=0;
    }
    else {
      prevactual=actual;
      actual=actual->next;
      if (actual==NULL)
	searching=0;
    }
  }
  if (!found) {
    aux=new(t_timeslot);
    if (aux!=NULL) {
      aux->next=actual;
      /*      if (last==NULL)
	      last=aux;*/
      if (prevactual==NULL)
	first=aux;
      else
	prevactual->next=aux;
      aux->slot=numslot;
      aux->link=(long*)calloc(maxlinks,sizeof(long));
      if (aux->link==NULL) {
	cerr<<"seekslot: Not enough memory for a new timeslot"<<endl;
	exit(-1);
      }
      for (c1=0;c1<maxlinks;c1++) {
	aux->link[c1]=0;
      }
      aux->userlink=(long*)calloc(maxusers,sizeof(long));
      if (aux->userlink==NULL) {
	cerr<<"seekslot: Not enough memory for a new timeslot"<<endl;
	exit(-1);
      }
      for (contusers=0;contusers<maxusers;contusers++)
	aux->userlink[contusers]=0;
      actual=aux;
    }
    else {
      cerr<<"seekslot: Not enough memory for a new timeslot"<<endl;
      exit(-1);
    }
  }
  return actual->link;
}
long* bwtable::seekuserslot(int numslot) {
  t_timeslot* actual=first,*aux,*prevactual=NULL;
  char found=0,searching=1;
  int c1;
  long contusers;

  if (actualslot>numslot) {
    cerr<<"seekslot: Trying to seek a past slot ("<<numslot
	<<"), actual is "<<actualslot<<endl;
    exit(-2);
    return NULL;
  }

  if (actual==NULL)
    searching=0;
  while (searching) {
    if (actual->slot==numslot) {
      found=1;
      searching=0;
    }
    else if (actual->slot>numslot) {
      searching=0;
    }
    else {
      prevactual=actual;
      actual=actual->next;
      if (actual==NULL)
	searching=0;
    }
  }
  if (!found) {
    aux=new(t_timeslot);
    if (aux!=NULL) {
      aux->next=actual;
      /*      if (last==NULL)
	      last=aux;*/
      if (prevactual==NULL)
	first=aux;
      else
	prevactual->next=aux;
      aux->slot=numslot;
      aux->link=(long*)calloc(maxlinks,sizeof(long));
      if (aux->link==NULL) {
	cerr<<"seekslot: Not enough memory for a new timeslot"<<endl;
	exit(-1);
      }
      for (c1=0;c1<maxlinks;c1++) {
	aux->link[c1]=0;
      }
      aux->userlink=(long*)calloc(maxusers,sizeof(long));
      if (aux->userlink==NULL) {
	cerr<<"seekslot: Not enough memory for a new timeslot"<<endl;
	exit(-1);
      }
      for (contusers=0;contusers<maxusers;contusers++)
	aux->userlink[contusers]=0;
      actual=aux;
    }
    else {
      cerr<<"seekslot: Not enough memory for a new timeslot"<<endl;
      exit(-1);
    }
  }
  return actual->userlink;
}

// returns if it is possible to add bw to numlink in numslot
int bwtable::testslot(long bw,int numslot,int numlink) {
  long* slot;

  slot=seekslot(numslot);
  if (slot!=NULL) {
    if ((slot[numlink]+bw)<=capacity[numlink])
      return 1;
    else
      return 0;
  }
  else {
    cerr<<"testslot: Slot does not exist ?¿?"<<endl;
    exit(-2);
  }
}
int bwtable::testuserslot(long bw,int numslot,long numuser) {
  long* userslot;

  if (numuser==-1) // reallocation
    return 1;
  userslot=seekuserslot(numslot);
  if (userslot!=NULL) {
    if ((userslot[numuser]+bw)<=usercapacity[numuser])
      return 1;
    else
      return 0;
  }
  else {
    cerr<<"testuserslot: Slot does not exist ?¿?"<<endl;
    exit(-2);
  }
}

// returns if a reserve has been made
int bwtable::reserveslot(long bw,int numslot,int numlink) {
  long* slot;

  slot=seekslot(numslot);
  if (slot!=NULL) {
    if ((slot[numlink]+bw)<=capacity[numlink]) {
      slot[numlink]+=bw;
      return 1;
    }
    else {
      cerr<<"reserveslot: Trying to reserve more bandwidth ("<<slot[numlink]+bw<<") than available ("<<capacity[numlink]<<") in slot "<<numslot<<")."<<endl;
      exit(-2);
    }
  }
  else {
    cerr<<"reserveslot: Slot does not exist ?¿?"<<endl;
    exit(-2);
  }
}
int bwtable::reserveuserslot(long bw,int numslot,long numuser) {
  long* userslot;

  if (numuser==-1) // reallocation
    return 1;
  userslot=seekuserslot(numslot);
  //cerr<<"rsvuslt "<<numslot<<": "<<userslot[numuser]<<"->"<<userslot[numuser]+bw<<endl;
  if (userslot!=NULL) {
    if ((userslot[numuser]+bw)<=usercapacity[numuser]) {
      userslot[numuser]+=bw;
      return 1;
    }
    else {
      cerr<<"reserveuserslot: Trying to reserve more bandwidth ("<<userslot[numuser]+bw<<") than available ("<<usercapacity[numuser]<<") in slot "<<numslot<<") for user "<<numuser<<"."<<endl;
      exit(-2);
    }
  }
  else {
    cerr<<"reserveuserslot: Slot does not exist ?¿?"<<endl;
    exit(-2);
  }
}

// returns if a reserve cancellation has been made
int bwtable::unreserveslot(long bw,int numslot,int numlink) {
  long* slot;

  slot=seekslot(numslot);
  if (slot!=NULL) {
    //cerr<<"slot "<<numslot<<" link "<<numlink<<" has "<<slot[numlink]<<endl;
    if ((slot[numlink]-bw)>=0) {
      slot[numlink]-=bw;
      return 1;
    }
    else {
      cerr<<"unreserveslot: Trying to unreserve more bandwidth than is reserved (slot "<<numslot<<")."<<endl;
      exit(-2);
    }
  }
  else {
    cerr<<"unreserverslot: Slot does not exist ?¿?"<<endl;
    exit(-2);
  }
}
int bwtable::unreserveuserslot(long bw,int numslot,long numuser) {
  long* userslot;

  if (numuser==-1) // reallocation
    return 1;
  userslot=seekuserslot(numslot);
  //cerr<<"ursvuslt "<<numslot<<": "<<userslot[numuser]<<"->"<<userslot[numuser]-bw<<endl;
  if (userslot!=NULL) {
    if ((userslot[numuser]-bw)>=0) {
      userslot[numuser]-=bw;
      return 1;
    }
    else {
      cerr<<"unreserveuserslot: Trying to unreserve more bandwidth than is reserved (slot "<<numslot<<")."<<endl;
      exit(-2);
    }
  }
  else {
    cerr<<"unreserveuserslot: Slot does not exist ?¿?"<<endl;
    exit(-2);
  }
}

// deletes old slots and plans, and returns the next used slot
int bwtable::delslotsto(int numslot) {
  t_timeslot* actual=first;
  char foundnewer=0;
  t_plan *myplan,*auxplan;
  int c1,c2;
  
  //numslot=(int)time;// delete slots lower than numslot
  if (numslot>=actualslot) {
    cerr<<"Trying to remove used slots"<<endl;
    exit(-2);
  }
  //  if (numslot<actualslot) {
    // delete table entries
    while ((!foundnewer)&&(first!=NULL)) {
      if (first->slot<=numslot) {
	actual=first->next;
	for (c2=0;c2<maxlinks;c2++) {
	  linktraffic[c2]=first->link[c2]; // slot utilization
	  //cerr<<first->link[c2];
	}
	free(first->link);
	free(first->userlink);
	delete(first);
	first=actual;
	/*if (first==NULL)
	  last=NULL;*/
      }
      else
	foundnewer=1;
    }
    //cerr<<"ok2"<<endl;
    // delete plan entries
    for (c1=0;c1<maxvideos;c1++) {
      myplan=planlistbyvid[c1];
      while (myplan!=NULL) {
	if ((myplan->start+myplan->duration)<numslot) { 
	  // following plans are not necessarilly older
	  if (planlistbyvid[c1]==myplan)
	    planlistbyvid[c1]=myplan->next;
	  else
	    myplan->prev->next=myplan->next;
	  if (myplan->next!=NULL)
	    myplan->next->prev=myplan->prev;
	  auxplan=myplan;
	  myplan=myplan->next;
	  free(auxplan->linklist);
	  free(auxplan->idlist);
	  delete(auxplan);
	}
	else 
	  myplan=myplan->next;
      }
    }
    //actualslot=numslot;
    //cerr<<"actual slot "<<actualslot<<endl;
    //}
  if (first!=NULL) {
    return first->slot;
  }
  else
    return 0;
}


/*int main() {
  bwtable lala(20,1000,20);
  }*/
