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