00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053 #ifndef ns_mcache_h
00054 #define ns_mcache_h
00055
00056 #include "config.h"
00057 #include "agent.h"
00058 #include "pagepool.h"
00059 #include "http.h"
00060 #include "rap/media-app.h"
00061
00062
00063
00064
00065
00066 class HitCount : public DoubleListElem {
00067 public:
00068 HitCount(ClientPage *pg, short layer) :
00069 DoubleListElem(), pg_(pg), layer_(layer), hc_(0) {}
00070
00071 void update(float hc) { hc_ += hc; }
00072 float hc() { return hc_; }
00073 void reset() { hc_ = 0; }
00074 ClientPage* page() { return pg_; }
00075 short layer() { return layer_; }
00076
00077 HitCount* next() { return (HitCount *)DoubleListElem::next(); }
00078 HitCount* prev() { return (HitCount *)DoubleListElem::prev(); }
00079
00080 private:
00081 ClientPage* pg_;
00082 short layer_;
00083 float hc_;
00084 };
00085
00086 class HitCountList : public DoubleList {
00087 public:
00088 HitCountList() : DoubleList() {}
00089
00090 void update(HitCount *h);
00091 void add(HitCount *h);
00092
00093 HitCount* detach_tail() {
00094 HitCount* tmp = (HitCount *)tail_;
00095 if (tmp) {
00096 tail_ = tail_->prev();
00097 tmp->detach();
00098 }
00099 return tmp;
00100 }
00101
00102
00103 void print();
00104 void check_integrity();
00105 };
00106
00107
00108
00109
00110
00111
00112 class MediaPage : public ClientPage {
00113 public:
00114 MediaPage(const char *n, int s, double mt, double et, double a, int l);
00115 virtual ~MediaPage();
00116
00117 virtual WebPageType type() const { return MEDIA; }
00118 virtual void print_info(char *buf);
00119 int num_layer() const { return num_layer_; }
00120
00121 HitCount* get_hit_count(int layer) {
00122 assert((layer >= 0) && (layer < num_layer_));
00123 return hc_[layer];
00124 }
00125 void hit_layer(int layer) {
00126 assert((layer >= 0) && (layer < num_layer_));
00127 hc_[layer]->update((double)(layer_[layer].length()*num_layer_)
00128 / (double)size_);
00129 }
00130
00131 int layer_size(int layer) {
00132 assert((layer >= 0) && (layer < num_layer_));
00133 return layer_[layer].length();
00134 }
00135 void add_segment(int layer, const MediaSegment& s);
00136 int evict_tail_segment(int layer, int size);
00137
00138 void add_layer(int layer) {
00139 assert((layer >= 0) && (layer < num_layer_));
00140 num_layer_ = (num_layer_ < layer) ? layer : num_layer_;
00141 }
00142 char* print_layer(int layer) {
00143 assert((layer >= 0) && (layer < num_layer_));
00144 return layer_[layer].dump2buf();
00145 }
00146 MediaSegmentList is_available(int layer, const MediaSegment& s) {
00147 assert((layer >= 0) && (layer < MAX_LAYER));
00148 return layer_[layer].check_holes(s);
00149 }
00150
00151
00152
00153
00154 MediaSegment next_available(int layer, const MediaSegment& s) {
00155 assert((layer >= 0) && (layer < MAX_LAYER));
00156 return layer_[layer].get_nextseg(s);
00157 }
00158 MediaSegment next_overlap(int layer, const MediaSegment& s) {
00159 assert((layer >= 0) && (layer < MAX_LAYER));
00160 MediaSegment s1 = layer_[layer].get_nextseg(s);
00161 if ((s1.end() <= s.start()) || (s1.start() >= s.end())) {
00162 MediaSegment s;
00163 if (s1.is_last())
00164 s.set_last();
00165 return s;
00166 } else
00167 return s1;
00168 }
00169
00170 enum {FETCHLOCK = 1, XMITLOCK = 2};
00171
00172
00173 void lock() { locked_ |= FETCHLOCK; }
00174 void unlock() { locked_ &= ~FETCHLOCK; }
00175 int is_locked() { return (locked_ & FETCHLOCK); }
00176
00177 void tlock() { locked_ |= XMITLOCK; }
00178 void tunlock() { locked_ &= ~XMITLOCK; }
00179 int is_tlocked() { return (locked_ & XMITLOCK); }
00180
00181
00182 int is_complete();
00183
00184 void set_complete();
00185
00186
00187
00188 void create();
00189 int realsize() const { return realsize_; }
00190
00191 protected:
00192 void set_complete_layer(int layer) {
00193 flags_[layer] = 1;
00194 }
00195 int is_complete_layer(int layer) {
00196 return flags_[layer] == 1;
00197 }
00198
00199 MediaSegmentList layer_[MAX_LAYER];
00200 int flags_[MAX_LAYER];
00201 HitCount* hc_[MAX_LAYER];
00202 int num_layer_;
00203 int locked_;
00204 int realsize_;
00205 };
00206
00207
00208
00209
00210
00211
00212
00213 class MClientPagePool : public ClientPagePool {
00214 public:
00215 MClientPagePool();
00216
00217 virtual ClientPage* enter_page(int argc, const char*const* argv);
00218 virtual int remove_page(const char *name);
00219 virtual int force_remove(const char *name);
00220
00221 int add_segment(const char *name, int layer, const MediaSegment& s);
00222 void hc_update(const char *name, int max_layer);
00223
00224 int maxsize() { return max_size_; }
00225 int usedsize() { return used_size_; }
00226
00227 void fill_page(const char* pgname);
00228
00229
00230 void dump_hclist() { hclist_.print(); }
00231
00232 protected:
00233 virtual int command(int argc, const char*const* argv);
00234 virtual int cache_replace(ClientPage* page, int size);
00235
00236
00237 int repl_finegrain(ClientPage* p, int size);
00238 int repl_atomic(ClientPage* p, int size);
00239
00240
00241 int max_size_;
00242 int used_size_;
00243 HitCountList hclist_;
00244
00245 enum { FINEGRAIN, ATOMIC } repl_style_;
00246 };
00247
00248
00249 class MediaPagePool : public PagePool {
00250 public:
00251 MediaPagePool();
00252 protected:
00253 virtual int command(int argc, const char*const* argv);
00254 int layer_;
00255 int *size_;
00256 RandomVariable *rvReq_;
00257 };
00258
00259
00260
00261
00262
00263
00264
00265
00266 class MediaCache : public HttpCache {
00267 public:
00268 MediaCache();
00269 ~MediaCache();
00270
00271
00272 virtual void process_data(int size, AppData* data);
00273
00274 virtual AppData* get_data(int& size, AppData* data);
00275
00276 protected:
00277 virtual int command(int argc, const char*const* argv);
00278
00279
00280
00281 MClientPagePool* mpool() { return (MClientPagePool *)pool_; }
00282
00283
00284 struct RegInfo {
00285 RegInfo() : client_(NULL), hl_(-1) {
00286 memset(pb_, 0, sizeof(unsigned int)*MAX_LAYER);
00287 memset(db_, 0, sizeof(unsigned int)*MAX_LAYER);
00288 memset(eb_, 0, sizeof(unsigned int)*MAX_LAYER);
00289 }
00290 ~RegInfo() {
00291 for (int i = 0; i < MAX_LAYER; i++)
00292 pref_[i].destroy();
00293 }
00294
00295 char name_[20];
00296 HttpApp* client_;
00297 int hl_;
00298
00299 unsigned int pb_[MAX_LAYER];
00300
00301 unsigned int eb_[MAX_LAYER];
00302
00303 unsigned int db_[MAX_LAYER];
00304 MediaSegmentList pref_[MAX_LAYER];
00305
00306
00307 void add_pref(int layer, const MediaSegment& s) {
00308 assert((layer >= 0) && (layer < MAX_LAYER));
00309 pref_[layer].add(s);
00310 }
00311 int pref_size(int layer, const MediaSegment &s) const {
00312 assert((layer >= 0) && (layer < MAX_LAYER));
00313 return pref_[layer].overlap_size(s);
00314 }
00315 };
00316 Tcl_HashTable *cmap_;
00317
00318
00319 enum {NOPREF, ONLINE_PREF, OFFLINE_PREF} pref_style_;
00320 };
00321
00322
00323
00324
00325
00326 class MediaClient : public HttpClient {
00327 public:
00328 MediaClient() : HttpClient() {}
00329 virtual void process_data(int size, AppData* data);
00330 virtual int command(int argc, const char*const* argv);
00331 private:
00332 MClientPagePool* mpool() { return (MClientPagePool *)pool_; }
00333 };
00334
00335
00336
00337
00338
00339 template <class T> class Queue;
00340
00341 template <class T> class QueueElem {
00342 public:
00343 QueueElem(T* d) : next_(0), data_(d) {}
00344
00345 QueueElem<T>* next() const { return next_; }
00346 T* data() const { return data_; }
00347 void detachData() { data_ = NULL; }
00348 void append(QueueElem<T>* e) {
00349 e->next_ = next_;
00350 next_ = e;
00351 }
00352
00353 protected:
00354 QueueElem<T>* next_;
00355 T* data_;
00356 friend class Queue<T>;
00357 };
00358
00359 template <class T> class Queue {
00360 public:
00361 Queue() : head_(0), tail_(0), size_(0) {}
00362 virtual ~Queue() {
00363 QueueElem<T> *p = head_, *q;
00364 while (p != NULL) {
00365 q = p;
00366 p = p->next();
00367 delete q;
00368 }
00369 head_ = NULL;
00370 }
00371 virtual void reset() {
00372 QueueElem<T> *p = head_, *q;
00373 while (p != NULL) {
00374 q = p;
00375 p = p->next();
00376 delete q;
00377 }
00378 head_ = NULL;
00379 }
00380 virtual void destroy() {
00381 QueueElem<T> *p = head_, *q;
00382 while (p != NULL) {
00383 q = p;
00384 p = p->next();
00385 delete q->data();
00386 delete q;
00387 }
00388 head_ = NULL;
00389 }
00390
00391 void enqueue(QueueElem<T> *e) {
00392 if (tail_ == 0)
00393 head_ = tail_ = e;
00394 else {
00395 tail_->append(e);
00396 tail_ = e;
00397 }
00398 size_++;
00399 }
00400 QueueElem<T>* dequeue() {
00401 QueueElem<T> *p = head_;
00402 if (head_ != 0)
00403 head_ = head_->next();
00404 if (head_ == 0)
00405 tail_ = 0;
00406 p->next_ = 0;
00407 size_--;
00408 if (size_ == 0)
00409 assert((head_ == 0) && (tail_ == 0));
00410 return p;
00411 }
00412 void detach(QueueElem<T>* e) {
00413 assert(head_ != 0);
00414 if (head_ == e) {
00415 dequeue();
00416 return;
00417 }
00418 QueueElem<T> *p = head_;
00419 while (p != NULL) {
00420 if (p->next_ != e)
00421 p = p->next_;
00422 else
00423 break;
00424 }
00425 assert(p != NULL);
00426 p->next_ = e->next_;
00427 if (tail_ == e)
00428 tail_ = p;
00429 size_--;
00430 if (size_ == 0)
00431 assert((head_ == 0) && (tail_ == 0));
00432 }
00433 QueueElem<T>* getHead() { return head_; }
00434 int is_empty() const { return (size_ == 0); }
00435 int size() const { return size_; }
00436
00437 protected:
00438 QueueElem<T> *head_, *tail_;
00439 int size_;
00440 };
00441
00442
00443
00444
00445
00446
00447 class MediaServer : public HttpServer {
00448 public:
00449 MediaServer();
00450 ~MediaServer();
00451 virtual AppData* get_data(int& size, AppData* d);
00452
00453 protected:
00454 virtual int command(int argc, const char*const* argv);
00455 MediaSegment get_next_segment(MediaRequest *r, Application*& ci);
00456
00457
00458 struct RegInfo {
00459 char name_[20];
00460 HttpApp* client_;
00461 };
00462 struct PrefInfo {
00463 MediaSegmentList* sl_;
00464 Application* conid_;
00465 };
00466 typedef Queue<PrefInfo> PrefInfoQ;
00467 typedef QueueElem<PrefInfo> PrefInfoE;
00468 PrefInfoE* find_prefinfo(PrefInfoQ* q, Application* conid) {
00469 for (PrefInfoE *e = q->getHead(); e != NULL; e = e->next())
00470 if (e->data()->conid_ == conid)
00471 return e;
00472 return NULL;
00473 }
00474
00475 Tcl_HashTable *pref_;
00476 Tcl_HashTable *cmap_;
00477
00478 PrefInfoQ* get_piq(const char* pgname, HttpApp* client) {
00479 PageID id;
00480 ClientPage::split_name(pgname, id);
00481 id.s_ = client;
00482 Tcl_HashEntry* he =
00483 Tcl_FindHashEntry(pref_, (const char*)&id);
00484 if (he == NULL)
00485 return NULL;
00486 return (PrefInfoQ*)Tcl_GetHashValue(he);
00487 }
00488 RegInfo* get_reginfo(Application* app) {
00489 Tcl_HashEntry *he =
00490 Tcl_FindHashEntry(cmap_, (const char *)app);
00491 if (he == NULL) {
00492 fprintf(stderr, "Unknown connection!\n");
00493 abort();
00494 }
00495 return (RegInfo *)Tcl_GetHashValue(he);
00496 }
00497 };
00498
00499
00500 #endif // ns_mcache_h