Main Page | Namespace List | Class Hierarchy | Alphabetical List | Compound List | File List | Compound Members | File Members

MediaSegmentList Class Reference

#include <media-app.h>

Inheritance diagram for MediaSegmentList:

Inheritance graph
[legend]
Collaboration diagram for MediaSegmentList:

Collaboration graph
[legend]
List of all members.

Public Member Functions

 MediaSegmentList ()
int length () const
void add (const MediaSegment &s)
int in (const MediaSegment &s)
MediaSegment get_nextseg (const MediaSegment &s)
int evict_tail (int size)
int evict_head (int size)
int evict_head_offset (int offset)
int overlap_size (const MediaSegment &s) const
MediaSegmentList check_holes (const MediaSegment &s)
char * dump2buf ()
virtual void destroy ()
void print (void)
int getsize ()
void check_integrity ()
DoubleListElemhead ()
DoubleListElemtail ()
void detach (DoubleListElem *e)
void insert (DoubleListElem *src, DoubleListElem *dst)
void append (DoubleListElem *src, DoubleListElem *dst)

Protected Member Functions

void merge_seg (MediaSegment *seg)

Protected Attributes

DoubleListElemhead_
DoubleListElemtail_

Private Attributes

int length_

Constructor & Destructor Documentation

MediaSegmentList::MediaSegmentList  )  [inline]
 

Definition at line 146 of file media-app.h.

References length_.

00146 : DoubleList(), length_(0) {}


Member Function Documentation

void MediaSegmentList::add const MediaSegment s  ) 
 

Definition at line 56 of file media-app.cc.

References abort(), DoubleList::append(), MediaSegment::before(), MediaSegment::datasize(), MediaSegment::end(), getsize(), DoubleList::head_, MediaSegment::in(), DoubleList::insert(), length_, MediaSegment::merge(), merge_seg(), MediaSegment::next(), MediaSegment::overlap(), print(), MediaSegment::start(), and DoubleList::tail_.

Referenced by MediaCache::RegInfo::add_pref(), MediaPage::add_segment(), check_holes(), and MediaServer::command().

00057 {
00058         MediaSegment* tmp = (MediaSegment *)head_;
00059         while ((tmp != NULL) && (tmp->before(s))) {
00060                 tmp = tmp->next();
00061         }
00062 
00063         // Append at the tail, or the first element in list
00064         if (tmp == NULL) {
00065                 length_ += s.datasize();
00066                 if ((tail_ != NULL) && ((MediaSegment *)tail_)->overlap(s)) 
00067                         // Don't need to merge because it's merged at the end
00068                         ((MediaSegment*)tail_)->merge(s);
00069                 else {
00070                         MediaSegment *p = new MediaSegment(s);
00071                         if (head_ == NULL)
00072                                 head_ = tail_ = p;
00073                         else 
00074                                 append(p, tail_);
00075                 }
00076                 if (getsize() != length_) {
00077                         fprintf(stderr, 
00078                                 "MediaSegmentList corrupted: Point 1.\n");
00079                         abort();
00080                 }
00081                 return;
00082         }
00083 
00084         // Update total stored length ONLY IF s is not in tmp.
00085         if (tmp->in(s)) {
00086                 fprintf(stderr, 
00087                         "MediaSegmentList: get a seg (%d %d) which is already in cache!\n",
00088                         s.start(), s.end());
00089                 fprintf(stderr, "List contents: ");
00090                 print();
00091 #if 0 
00092                 //Tcl::instance().eval("[Simulator instance] flush-trace");
00093                 //abort();
00094 #endif
00095                 // XXX Don't abort, simply continue
00096                 return;
00097         }
00098 
00099         // Insert a MediaSegment into list. Note: Don't do merge!
00100         if (tmp->overlap(s)) {
00101                 length_ += (s.datasize() - tmp->merge(s));
00102         } else {
00103                 MediaSegment *p = new MediaSegment(s);
00104                 insert(p, tmp);
00105                 tmp = p;
00106                 length_ += s.datasize();
00107         }
00108 
00109         if (getsize() != length_) {
00110                 fprintf(stderr, "MediaSegmentList corrupted: Point 2.\n");
00111                 abort();
00112         }
00113 
00114         merge_seg(tmp);
00115 
00116         if (getsize() != length_) {
00117                 fprintf(stderr, "MediaSegmentList corrupted: Point 3.\n");
00118                 abort();
00119         }
00120 }

Here is the call graph for this function:

void DoubleList::append DoubleListElem src,
DoubleListElem dst
[inline, inherited]
 

Definition at line 111 of file utilities.h.

References DoubleListElem::append(), and DoubleList::tail_.

Referenced by add(), HitCountList::add(), and HitCountList::update().

00111                                                               {
00112                 dst->append(src);
00113                 if (dst == tail_)
00114                         tail_ = src;
00115         }

Here is the call graph for this function:

MediaSegmentList MediaSegmentList::check_holes const MediaSegment s  ) 
 

Definition at line 282 of file media-app.cc.

References add(), MediaSegment::before(), check_integrity(), MediaSegment::end(), DoubleList::head_, in(), MediaSegment::in(), min, MediaSegment::next(), MediaSegment::overlap(), print(), and MediaSegment::start().

Referenced by MediaPage::is_available().

00283 {
00284         MediaSegmentList res;  // empty list
00285         MediaSegment* tmp = (MediaSegment *)head_;
00286         while ((tmp != NULL) && (tmp->before(s)))
00287                 tmp = tmp->next();
00288         // If all segments are before s, s is a hole
00289         if (tmp == NULL) {
00290                 res.add(s);
00291                 return res;
00292         }
00293         // If s is within *tmp, there is no hole
00294         if (s.in(*tmp))
00295                 return res;
00296 
00297         // Otherwise return a list of holes
00298         int soff, eoff;
00299         soff = s.start();
00300         eoff = s.end();
00301         while ((tmp != NULL) && (tmp->overlap(s))) {
00302                 if (soff < tmp->start()) {
00303                         // Only refetches the missing part
00304                         res.add(MediaSegment(soff, min(eoff, tmp->start())));
00305 #if 1
00306                         // DEBUG ONLY
00307                         // Check if these holes are really holes!
00308                         if (in(MediaSegment(soff, min(eoff, tmp->start())))) {
00309                                 fprintf(stderr, "Wrong hole: (%d %d) ", 
00310                                         soff, min(eoff, tmp->start()));
00311                                 fprintf(stderr, "tmp(%d %d), s(%d %d)\n",
00312                                         tmp->start(), tmp->end(),
00313                                         soff, eoff);
00314                                 fprintf(stderr, "List content: ");
00315                                 print();
00316                         }
00317 #endif
00318                 }
00319                 soff = tmp->end();
00320                 tmp = tmp->next();
00321         }
00322         if (soff < eoff) {
00323                 res.add(MediaSegment(soff, eoff));
00324 #if 1           
00325                 // DEBUG ONLY
00326                 // Check if these holes are really holes!
00327                 if (in(MediaSegment(soff, eoff))) {
00328                         fprintf(stderr, "Wrong hole #2: (%d %d)\n", 
00329                                 soff, eoff);
00330                         fprintf(stderr, "List content: ");
00331                         print();
00332                 }
00333 #endif
00334         }
00335 #if 0
00336         check_integrity();
00337 #endif
00338         return res;
00339 }

Here is the call graph for this function:

void MediaSegmentList::check_integrity  ) 
 

Definition at line 341 of file media-app.cc.

References abort(), MediaSegment::before(), MediaSegment::end(), DoubleList::head_, MediaSegment::next(), and MediaSegment::start().

Referenced by check_holes().

00342 {
00343         MediaSegment *p, *q;
00344         p = (MediaSegment*)head_;
00345         while (p != NULL) {
00346                 q = p; 
00347                 p = p->next();
00348                 if (p == NULL)
00349                         break;
00350                 if (!q->before(*p)) {
00351                         fprintf(stderr, 
00352                                 "Invalid segment added: (%d %d), (%d %d)\n", 
00353                                 q->start(), q->end(), p->start(), p->end());
00354                         abort();
00355                 }
00356         }
00357 }

Here is the call graph for this function:

virtual void MediaSegmentList::destroy  )  [inline, virtual]
 

Reimplemented from DoubleList.

Definition at line 159 of file media-app.h.

References DoubleList::destroy(), and length_.

Referenced by MediaServer::command(), MediaPage::create(), MediaCache::get_data(), MediaPage::~MediaPage(), MediaServer::~MediaServer(), and MediaCache::RegInfo::~RegInfo().

00159                                {
00160                 DoubleList::destroy();
00161                 length_ = 0;
00162         }

Here is the call graph for this function:

void DoubleList::detach DoubleListElem e  )  [inline, inherited]
 

Definition at line 99 of file utilities.h.

References DoubleListElem::detach(), DoubleList::head_, DoubleListElem::next(), DoubleListElem::prev(), and DoubleList::tail_.

Referenced by evict_head(), evict_head_offset(), evict_tail(), MClientPagePool::force_remove(), merge_seg(), MClientPagePool::repl_atomic(), MClientPagePool::repl_finegrain(), and HitCountList::update().

00099                                        {
00100                 if (head_ == e)
00101                         head_ = e->next();
00102                 if (tail_ == e)
00103                         tail_ = e->prev();
00104                 e->detach();
00105         }

Here is the call graph for this function:

char * MediaSegmentList::dump2buf  ) 
 

Definition at line 414 of file media-app.cc.

References MediaSegment::end(), DoubleList::head_, MediaSegment::next(), and MediaSegment::start().

Referenced by MediaCache::get_data(), and MediaPage::print_layer().

00415 {
00416         char *buf = new char[1024];
00417         char *b = buf;
00418         MediaSegment *p = (MediaSegment *)head_;
00419         int i = 0, sz = 1024;
00420         buf[0] = 0;
00421         while (p != NULL) {
00422                 // XXX snprintf() should either be in libc or implemented
00423                 // by TclCL (see Tcl2.cc there).
00424                 i = snprintf(b, sz, "{%d %d} ", p->start(), p->end());
00425                 sz -= i;
00426                 // Boundary check: if less than 50 bytes, allocate new buf
00427                 if (sz < 50) {
00428                         char *tmp = new char[strlen(buf)+1024];
00429                         strcpy(tmp, buf);
00430                         delete []buf;
00431                         buf = tmp;
00432                         b = buf + strlen(buf);
00433                         sz += 1024;
00434                 } else 
00435                         b += i;
00436                 p = p->next();
00437         }
00438         return buf;
00439 }

Here is the call graph for this function:

int MediaSegmentList::evict_head int  size  ) 
 

Definition at line 236 of file media-app.cc.

References MediaSegment::datasize(), DoubleList::detach(), MediaSegment::evict_head(), DoubleList::head_, and length_.

00237 {
00238         int sz = size, tz;
00239         MediaSegment *tmp = (MediaSegment *)head_;
00240         while ((tmp != NULL) && (sz > 0)) {
00241                 // Reduce the last segment's size and adjust its playout time
00242                 tz = tmp->evict_head(sz);
00243                 sz -= tz; 
00244                 length_ -= tz;
00245                 if (tmp->datasize() == 0) {
00246                         // This segment is empty now
00247                         detach(tmp);
00248                         delete tmp;
00249                         tmp = (MediaSegment *)head_;
00250                 }
00251         }
00252         return size - sz;
00253 }

Here is the call graph for this function:

int MediaSegmentList::evict_head_offset int  offset  ) 
 

Definition at line 257 of file media-app.cc.

References MediaSegment::datasize(), DoubleList::detach(), MediaSegment::end(), DoubleList::head_, length_, MediaSegment::set_start(), MediaSegment::start(), and DoubleList::tail_.

Referenced by QA::DrainBuffers().

00258 {
00259         int sz = 0;
00260         MediaSegment *tmp = (MediaSegment *)head_;
00261         while ((tmp != NULL) && (tmp->start() < offset)) {
00262                 if (tmp->end() <= offset) {
00263                         // delete whole segment
00264                         sz += tmp->datasize();
00265                         length_ -= tmp->datasize();
00266                         detach(tmp);
00267                         delete tmp;
00268                         tmp = (MediaSegment *)head_;
00269                 } else {
00270                         // remove part of the segment
00271                         sz += offset - tmp->start();
00272                         length_ -= offset - tmp->start();
00273                         tmp->set_start(offset);
00274                 }
00275         }
00276         if (head_ == NULL)
00277                 tail_ = NULL;
00278         return sz;
00279 }

Here is the call graph for this function:

int MediaSegmentList::evict_tail int  size  ) 
 

Definition at line 216 of file media-app.cc.

References MediaSegment::datasize(), DoubleList::detach(), MediaSegment::evict_tail(), length_, and DoubleList::tail_.

Referenced by MediaPage::evict_tail_segment().

00217 {
00218         int sz = size, tz;
00219         MediaSegment *tmp = (MediaSegment *)tail_;
00220         while ((tmp != NULL) && (sz > 0)) {
00221                 // Reduce the last segment's size and adjust its playout time
00222                 tz = tmp->evict_tail(sz);
00223                 length_ -= tz;
00224                 sz -= tz; 
00225                 if (tmp->datasize() == 0) {
00226                         // This segment is empty now
00227                         detach(tmp);
00228                         delete tmp;
00229                         tmp = (MediaSegment *)tail_;
00230                 }
00231         }
00232         return size - sz;
00233 }

Here is the call graph for this function:

MediaSegment MediaSegmentList::get_nextseg const MediaSegment s  ) 
 

Definition at line 164 of file media-app.cc.

References MediaSegment::before(), MediaSegment::datasize(), MediaSegment::end(), DoubleList::head_, MediaSegment::next(), MediaSegment::set_datasize(), MediaSegment::set_last(), MediaSegment::set_start(), and MediaSegment::start().

Referenced by MediaServer::get_next_segment(), MediaPage::next_available(), and MediaPage::next_overlap().

00165 {
00166         MediaSegment res(0, 0); // If unsuccessful, return start() = 0
00167 
00168         MediaSegment* tmp = (MediaSegment *)head_;
00169         while ((tmp != NULL) && (tmp->before(s))) 
00170                 tmp = tmp->next();
00171         if (tmp == NULL) {
00172                 res.set_last();
00173                 return res;
00174         }
00175         assert(tmp->end() > s.start());
00176 //      // Don't return a segment which do not *OVERLAP* with s 
00177 //      // (boundary overlap is excluded).
00178 //      if ((tmp->end() <= s.start()) || (tmp->start() >= s.end())) 
00179 //          return res;
00180 
00181         // XXX How to flag that no more data is available in the future??
00182         res = s;
00183         int orig_size = s.datasize();
00184         if (res.start() < tmp->start()) {
00185                 // |-------| (s)    ---> time axis
00186                 //    |--------| (tmp)
00187                 //
00188                 // The start time of s is invalid, we need to adjust both 
00189                 // the start time (and size if necessary)
00190                 res.set_start(tmp->start());
00191                 if (tmp->datasize() < orig_size) 
00192                         // Not enough data available??
00193                         res.set_datasize(tmp->datasize());
00194                 else
00195                         res.set_datasize(orig_size);
00196         } else if (res.end() > tmp->end()) {
00197                 //    |---------| (s)    ---> time axis
00198                 // |-------| (tmp)
00199                 // 
00200                 // The start time in s is valid, but we may need to adjust the 
00201                 // end time (i.e., size) of s.
00202                 res.set_datasize(tmp->end()-res.start());
00203         }
00204         // Falling through means that the requested segment is available 
00205         // and can be returned as it is.
00206 
00207         assert(res.datasize() <= tmp->datasize());
00208         if ((res.end() == tmp->end()) && (tmp->next() == NULL))
00209                 // This is the last data segment of the layer
00210                 res.set_last();
00211         return res;
00212 }

Here is the call graph for this function:

int MediaSegmentList::getsize  ) 
 

Definition at line 402 of file media-app.cc.

References MediaSegment::datasize(), DoubleList::head_, and MediaSegment::next().

Referenced by add().

00403 {
00404         MediaSegment *p = (MediaSegment *)head_;
00405         int sz = 0;
00406         while (p != NULL) {
00407                 sz += p->datasize();
00408                 p = p->next();
00409         }
00410         return sz;
00411 }

Here is the call graph for this function:

DoubleListElem* DoubleList::head  )  [inline, inherited]
 

Definition at line 96 of file utilities.h.

References DoubleList::head_.

00096 { return head_; }

int MediaSegmentList::in const MediaSegment s  ) 
 

Definition at line 148 of file media-app.cc.

References MediaSegment::before(), DoubleList::head_, MediaSegment::in(), and MediaSegment::next().

Referenced by check_holes().

00149 {
00150         MediaSegment* tmp = (MediaSegment *)head_;
00151         while ((tmp != NULL) && (tmp->before(s)))
00152                 tmp = tmp->next();
00153 
00154         // If all segments are before s, or the first segment which isn't 
00155         // before s doesn't overlap with s, s isn't in this list.
00156         if ((tmp == NULL) || !s.in(*tmp))
00157                 return 0;
00158         else 
00159                 return 1;
00160 }

Here is the call graph for this function:

void DoubleList::insert DoubleListElem src,
DoubleListElem dst
[inline, inherited]
 

Definition at line 106 of file utilities.h.

References DoubleList::head_, and DoubleListElem::insert().

Referenced by add(), HitCountList::add(), and HitCountList::update().

00106                                                               {
00107                 dst->insert(src);
00108                 if (dst == head_)
00109                         head_ = src;
00110         }

Here is the call graph for this function:

int MediaSegmentList::length  )  const [inline]
 

Definition at line 148 of file media-app.h.

References length_.

Referenced by MediaCache::get_data(), MediaServer::get_next_segment(), MediaPage::is_complete(), and MediaPage::layer_size().

00148 { return length_; }

void MediaSegmentList::merge_seg MediaSegment seg  )  [protected]
 

Definition at line 122 of file media-app.cc.

References abort(), DoubleList::detach(), MediaSegment::end(), MediaSegment::merge(), MediaSegment::next(), MediaSegment::overlap(), MediaSegment::prev(), MediaSegment::start(), and DoubleList::tail_.

Referenced by add().

00123 {
00124         // See if <tmp> can be merged with next segments
00125         MediaSegment *q = tmp->next();
00126         while (q && q->overlap(*tmp)) {
00127 #if 1
00128                 if ((tmp->start() == q->start()) && (tmp->end() == q->end())) {
00129                         abort();
00130                 }
00131 #endif
00132                 tmp->merge(*q);
00133                 detach(q);
00134                 delete q;
00135                 q = tmp->next();
00136         }
00137         // See if <tmp> can be merged with previous segments
00138         q = tmp->prev();
00139         while (q && q->overlap(*tmp)) {
00140                 tmp->merge(*q);
00141                 assert(tail_ != q);
00142                 detach(q);
00143                 delete q;
00144                 q = tmp->prev();
00145         }
00146 }

Here is the call graph for this function:

int MediaSegmentList::overlap_size const MediaSegment s  )  const
 

Definition at line 362 of file media-app.cc.

References MediaSegment::before(), MediaSegment::datasize(), MediaSegment::end(), DoubleList::head_, MediaSegment::in(), max, min, MediaSegment::next(), MediaSegment::overlap(), and MediaSegment::start().

Referenced by MediaCache::RegInfo::pref_size().

00363 {
00364         int res = 0;
00365         MediaSegment* tmp = (MediaSegment *)head_;
00366         while ((tmp != NULL) && (tmp->before(s)))
00367                 tmp = tmp->next();
00368         // If all segments are before s, there's no overlap
00369         if (tmp == NULL)
00370                 return 0;
00371         // If s is within *tmp, entire s overlaps with the list
00372         if (s.in(*tmp))
00373                 return s.datasize();
00374         // Otherwise adds all overlapping parts together.
00375         int soff, eoff;
00376         soff = s.start();
00377         eoff = s.end();
00378         while ((tmp != NULL) && (tmp->overlap(s))) {
00379                 res += min(eoff, tmp->end()) - max(soff, tmp->start());
00380                 soff = tmp->end();
00381                 tmp = tmp->next();
00382         }
00383         return res;
00384 }

Here is the call graph for this function:

void MediaSegmentList::print void   ) 
 

Definition at line 387 of file media-app.cc.

References MediaSegment::datasize(), MediaSegment::end(), DoubleList::head_, MediaSegment::next(), and MediaSegment::start().

Referenced by add(), and check_holes().

00388 {
00389         MediaSegment *p = (MediaSegment *)head_;
00390         int i = 0, sz = 0;
00391         while (p != NULL) {
00392                 printf("(%d, %d)  ", p->start(), p->end());
00393                 sz += p->datasize();
00394                 p = p->next();
00395                 if (++i % 8 == 0)
00396                         printf("\n");
00397         }
00398         printf("\nTotal = %d\n", sz);
00399 }

Here is the call graph for this function:

DoubleListElem* DoubleList::tail  )  [inline, inherited]
 

Definition at line 97 of file utilities.h.

References DoubleList::tail_.

Referenced by MClientPagePool::repl_atomic(), and MClientPagePool::repl_finegrain().

00097 { return tail_; }


Member Data Documentation

DoubleListElem* DoubleList::head_ [protected, inherited]
 

Definition at line 117 of file utilities.h.

Referenced by add(), HitCountList::add(), check_holes(), check_integrity(), HitCountList::check_integrity(), DoubleList::destroy(), DoubleList::detach(), DoubleList::DoubleList(), dump2buf(), evict_head(), evict_head_offset(), get_nextseg(), getsize(), DoubleList::head(), in(), DoubleList::insert(), overlap_size(), print(), HitCountList::print(), and HitCountList::update().

int MediaSegmentList::length_ [private]
 

Definition at line 173 of file media-app.h.

Referenced by add(), destroy(), evict_head(), evict_head_offset(), evict_tail(), length(), and MediaSegmentList().

DoubleListElem * DoubleList::tail_ [protected, inherited]
 

Definition at line 117 of file utilities.h.

Referenced by add(), HitCountList::add(), DoubleList::append(), DoubleList::destroy(), DoubleList::detach(), HitCountList::detach_tail(), DoubleList::DoubleList(), evict_head_offset(), evict_tail(), merge_seg(), DoubleList::tail(), and HitCountList::update().


The documentation for this class was generated from the following files:
Generated on Tue Apr 20 13:00:06 2004 for NS2.26SourcesOriginal by doxygen 1.3.3