mcache.h
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:14k
源码类别:

通讯编程

开发平台:

Visual C++

  1. /* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
  2. /*
  3.  * mcache.h
  4.  * Copyright (C) 1997 by the University of Southern California
  5.  * $Id: mcache.h,v 1.8 2005/09/18 23:33:35 tomh Exp $
  6.  *
  7.  * This program is free software; you can redistribute it and/or
  8.  * modify it under the terms of the GNU General Public License,
  9.  * version 2, as published by the Free Software Foundation.
  10.  *
  11.  * This program is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  * GNU General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU General Public License along
  17.  * with this program; if not, write to the Free Software Foundation, Inc.,
  18.  * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
  19.  *
  20.  *
  21.  * The copyright of this module includes the following
  22.  * linking-with-specific-other-licenses addition:
  23.  *
  24.  * In addition, as a special exception, the copyright holders of
  25.  * this module give you permission to combine (via static or
  26.  * dynamic linking) this module with free software programs or
  27.  * libraries that are released under the GNU LGPL and with code
  28.  * included in the standard release of ns-2 under the Apache 2.0
  29.  * license or under otherwise-compatible licenses with advertising
  30.  * requirements (or modified versions of such code, with unchanged
  31.  * license).  You may copy and distribute such a system following the
  32.  * terms of the GNU GPL for this module and the licenses of the
  33.  * other code concerned, provided that you include the source code of
  34.  * that other code when and as the GNU GPL requires distribution of
  35.  * source code.
  36.  *
  37.  * Note that people who make modified versions of this module
  38.  * are not obligated to grant this special exception for their
  39.  * modified versions; it is their choice whether to do so.  The GNU
  40.  * General Public License gives permission to release a modified
  41.  * version without this exception; this exception also makes it
  42.  * possible to release a modified version which carries forward this
  43.  * exception.
  44.  *
  45.  */
  46. //
  47. // Multimedia caches
  48. // 
  49. // $Header: /cvsroot/nsnam/ns-2/webcache/mcache.h,v 1.8 2005/09/18 23:33:35 tomh Exp $
  50. #ifndef ns_mcache_h
  51. #define ns_mcache_h
  52. #include "config.h"
  53. #include "agent.h"
  54. #include "pagepool.h"
  55. #include "http.h"
  56. #include "rap/media-app.h"
  57. //----------------------------------------------------------------------
  58. // Priority list for hit counts at each layer
  59. //----------------------------------------------------------------------
  60. class HitCount : public DoubleListElem {
  61. public:
  62. HitCount(ClientPage *pg, short layer) : 
  63. DoubleListElem(), pg_(pg), layer_(layer), hc_(0) {}
  64. void update(float hc) { hc_ += hc; }
  65. float hc() { return hc_; }
  66. void reset() { hc_ = 0; }
  67. ClientPage* page() { return pg_; }
  68. short layer() { return layer_; }
  69. HitCount* next() { return (HitCount *)DoubleListElem::next(); }
  70. HitCount* prev() { return (HitCount *)DoubleListElem::prev(); }
  71. private:
  72. ClientPage* pg_;  // page
  73. short layer_;  // layer id
  74. float hc_; // hit count
  75. };
  76. class HitCountList : public DoubleList {
  77. public:
  78. HitCountList() : DoubleList() {}
  79. void update(HitCount *h);  // Update layer hit count
  80. void add(HitCount *h); // Add a new layer
  81. HitCount* detach_tail() {
  82. HitCount* tmp = (HitCount *)tail_;
  83. if (tmp) {
  84. tail_ = tail_->prev();
  85. tmp->detach();
  86. }
  87. return tmp;
  88. }
  89. // Debug only
  90. void print();
  91. void check_integrity(); 
  92. };
  93. //----------------------------------------------------------------------
  94. // Multimedia web objects
  95. //----------------------------------------------------------------------
  96. class MediaPage : public ClientPage {
  97. public:
  98. MediaPage(const char *n, int s, double mt, double et, double a, int l);
  99. virtual ~MediaPage();
  100. virtual WebPageType type() const { return MEDIA; }
  101. virtual void print_info(char *buf);
  102. int num_layer() const { return num_layer_; }
  103. HitCount* get_hit_count(int layer) { 
  104. assert((layer >= 0) && (layer < num_layer_));
  105. return hc_[layer]; 
  106. }
  107. void hit_layer(int layer) {
  108. assert((layer >= 0) && (layer < num_layer_));
  109. hc_[layer]->update((double)(layer_[layer].length()*num_layer_)
  110.    / (double)size_); 
  111. }
  112. int layer_size(int layer) { 
  113. assert((layer >= 0) && (layer < num_layer_));
  114. return layer_[layer].length();
  115. }
  116. void add_segment(int layer, const MediaSegment& s);
  117. int evict_tail_segment(int layer, int size);
  118. void add_layer(int layer) {
  119. assert((layer >= 0) && (layer < num_layer_));
  120. num_layer_ = (num_layer_ < layer) ? layer : num_layer_;
  121. }
  122. char* print_layer(int layer) {
  123. assert((layer >= 0) && (layer < num_layer_));
  124. return layer_[layer].dump2buf();
  125. }
  126. MediaSegmentList is_available(int layer, const MediaSegment& s) {
  127. assert((layer >= 0) && (layer < MAX_LAYER));
  128. return layer_[layer].check_holes(s);
  129. }
  130. // Return a media segment which is the closest one after 's'.
  131. // Used by MediaApps to request data.
  132. // Do NOT check if layer >= num_layer_. If it's empty, 
  133. // an empty MediaSegment will be returned. 
  134. MediaSegment next_available(int layer, const MediaSegment& s) {
  135. assert((layer >= 0) && (layer < MAX_LAYER));
  136. return layer_[layer].get_nextseg(s);
  137. }
  138. MediaSegment next_overlap(int layer, const MediaSegment& s) {
  139. assert((layer >= 0) && (layer < MAX_LAYER));
  140. MediaSegment s1 = layer_[layer].get_nextseg(s);
  141. if ((s1.end() <= s.start()) || (s1.start() >= s.end())) {
  142. MediaSegment s;
  143. if (s1.is_last())
  144. s.set_last();
  145. return s;
  146. } else
  147. return s1;
  148. }
  149. enum {FETCHLOCK = 1, XMITLOCK = 2};
  150. // 1st type of lock: it is being fetched from the server
  151. void lock() { locked_ |= FETCHLOCK; }
  152. void unlock() { locked_ &= ~FETCHLOCK; }
  153. int is_locked() { return (locked_ & FETCHLOCK); }
  154. // 2nd type of lock: it is being transmitted to a client
  155. void tlock() { locked_ |= XMITLOCK; }
  156. void tunlock() { locked_ &= ~XMITLOCK; }
  157. int is_tlocked() { return (locked_ & XMITLOCK); }
  158. // Whether all layers are marked as "completed"
  159. int is_complete(); 
  160. // Set all layers as "completed"
  161. void set_complete();
  162. // Given the number of layers, evenly distribute the size among all
  163. // layers and create all segments.
  164. void create();
  165. int realsize() const { return realsize_; }
  166. protected:
  167. void set_complete_layer(int layer) {
  168. flags_[layer] = 1;
  169. }
  170. int is_complete_layer(int layer) {
  171. return flags_[layer] == 1; 
  172. }
  173. MediaSegmentList layer_[MAX_LAYER];
  174. int flags_[MAX_LAYER]; // If 1, marks the layer as completed
  175. HitCount* hc_[MAX_LAYER];
  176. int num_layer_; 
  177. int locked_;  // If 1, then no segment can be replaced
  178. int realsize_; // The size of stream data in this page.
  179. };
  180. // XXX Later we should add a generic replacement algorithm hook into 
  181. // ClientPagePool. But now we'll leave it there and get this media 
  182. // page pool work first. 
  183. // ClientPagePool enhanced with support for multimedia objects, and 
  184. // with replacement algorithms
  185. class MClientPagePool : public ClientPagePool {
  186. public:
  187. MClientPagePool();
  188. virtual ClientPage* enter_page(int argc, const char*const* argv);
  189. virtual int remove_page(const char *name);
  190. virtual int force_remove(const char *name);
  191. int add_segment(const char *name, int layer, const MediaSegment& s);
  192. void hc_update(const char *name, int max_layer);
  193. int maxsize() { return max_size_; }
  194. int usedsize() { return used_size_; }
  195. void fill_page(const char* pgname);
  196. // Debug only
  197. void dump_hclist() { hclist_.print(); }
  198. protected:
  199. virtual int command(int argc, const char*const* argv);
  200. virtual int cache_replace(ClientPage* page, int size);
  201. // Fine-grain replacement
  202. int repl_finegrain(ClientPage* p, int size);
  203. int repl_atomic(ClientPage* p, int size);
  204. // XXX Should change to quad_t, or use MB as unit
  205. int max_size_;  // PagePool size
  206. int used_size_; // Available space size
  207. HitCountList hclist_; 
  208. // Replacement style
  209. enum { FINEGRAIN, ATOMIC } repl_style_;
  210. };
  211. // Provide page data and generate requests for servers and clients
  212. class MediaPagePool : public PagePool {
  213. public:
  214. MediaPagePool();
  215. protected:
  216. virtual int command(int argc, const char*const* argv);
  217. int layer_; // Number of layers of pages
  218. int *size_;  // Page sizes
  219. RandomVariable *rvReq_;
  220. };
  221. //--------------------
  222. // Multimedia caches
  223. //--------------------
  224. // Plain multimedia cache, which can interface with RapAgent
  225. class MediaCache : public HttpCache {
  226. public:
  227. MediaCache();
  228. ~MediaCache();
  229. // Handle app-specific data in C++
  230. virtual void process_data(int size, AppData* data);
  231. // Handle data request from RAP
  232. virtual AppData* get_data(int& size, AppData* data);
  233. protected:
  234. virtual int command(int argc, const char*const* argv);
  235. // Do we need to maintain links to MediaApp?? I doubt not
  236. // MediaApp* mapp_; // An array of incoming/outgoing RAP agents
  237. MClientPagePool* mpool() { return (MClientPagePool *)pool_; }
  238. // Information and statistics related to clients
  239. struct RegInfo {
  240. RegInfo() : client_(NULL), hl_(-1) {
  241. memset(pb_, 0, sizeof(unsigned int)*MAX_LAYER);
  242. memset(db_, 0, sizeof(unsigned int)*MAX_LAYER);
  243. memset(eb_, 0, sizeof(unsigned int)*MAX_LAYER);
  244. }
  245. ~RegInfo() {
  246. for (int i = 0; i < MAX_LAYER; i++)
  247. pref_[i].destroy();
  248. }
  249. char name_[20];
  250. HttpApp* client_;
  251. int hl_; // Highest layer this client has asked
  252. // Prefetched bytes
  253. unsigned int pb_[MAX_LAYER]; 
  254. // Prefetched bytes that were delivered
  255. unsigned int eb_[MAX_LAYER];
  256. // Total delivered bytes
  257. unsigned int db_[MAX_LAYER];
  258. MediaSegmentList pref_[MAX_LAYER];
  259. // Return the number of prefetched bytes in the given segment
  260. void add_pref(int layer, const MediaSegment& s) {
  261. assert((layer >= 0) && (layer < MAX_LAYER));
  262. pref_[layer].add(s);
  263. }
  264. int pref_size(int layer, const MediaSegment &s) const { 
  265. assert((layer >= 0) && (layer < MAX_LAYER));
  266. return pref_[layer].overlap_size(s);
  267. }
  268. };
  269. Tcl_HashTable *cmap_; // client map
  270. // Prefetching/No-prefetching/Offline-prefetching flag
  271. enum {NOPREF, ONLINE_PREF, OFFLINE_PREF} pref_style_;
  272. };
  273. //----------------------------------------------------------------------
  274. // Multimedia web client
  275. //----------------------------------------------------------------------
  276. class MediaClient : public HttpClient {
  277. public:
  278. MediaClient() : HttpClient() {}
  279. virtual void process_data(int size, AppData* data);
  280. virtual int command(int argc, const char*const* argv);
  281. private:
  282. MClientPagePool* mpool() { return (MClientPagePool *)pool_; }
  283. };
  284. // Helper data structure
  285. template <class T> class Queue; // forward declaration
  286. template <class T> class QueueElem {
  287. public:
  288.         QueueElem(T* d) : next_(0), data_(d) {}
  289.         QueueElem<T>* next() const { return next_; }
  290.         T* data() const { return data_; }
  291.         void detachData() { data_ = NULL; }
  292.         void append(QueueElem<T>* e) {
  293.                 e->next_ = next_;
  294.                 next_ = e;
  295.         }
  296. protected:
  297.         QueueElem<T>* next_;
  298.         T* data_;
  299. friend class Queue<T>; 
  300. };
  301. template <class T> class Queue {
  302. public:
  303.         Queue() : head_(0), tail_(0), size_(0) {}
  304.         virtual ~Queue() {
  305.                 QueueElem<T> *p = head_, *q;
  306.                 while (p != NULL) {
  307.                         q = p;
  308.                         p = p->next();
  309.                         delete q;
  310.                 }
  311.                 head_ = NULL;
  312.         }
  313.         virtual void reset() {
  314.                 QueueElem<T> *p = head_, *q;
  315.                 while (p != NULL) {
  316.                         q = p;
  317.                         p = p->next();
  318.                         delete q;
  319.                 }
  320.                 head_ = NULL;
  321.         }
  322.         virtual void destroy() {
  323.                 QueueElem<T> *p = head_, *q;
  324.                 while (p != NULL) {
  325.                         q = p;
  326.                         p = p->next();
  327.                         delete q->data();
  328.                         delete q;
  329.                 }
  330.                 head_ = NULL;
  331.         }
  332.         void enqueue(QueueElem<T> *e) {
  333.                 if (tail_ == 0)
  334.                         head_ = tail_ = e;
  335.                 else {
  336.                         tail_->append(e);
  337. tail_ = e;
  338. }
  339.                 size_++;
  340.         }
  341.         QueueElem<T>* dequeue() {
  342.                 QueueElem<T> *p = head_;
  343.                 if (head_ != 0) 
  344.                         head_ = head_->next();
  345.                 if (head_ == 0)
  346.                         tail_ = 0;
  347.                 p->next_ = 0;
  348.                 size_--;
  349. if (size_ == 0) 
  350. assert((head_ == 0) && (tail_ == 0));
  351.                 return p;
  352.         }
  353. void detach(QueueElem<T>* e) {
  354. assert(head_ != 0);
  355. if (head_ == e) {
  356. dequeue();
  357. return;
  358. }
  359. QueueElem<T> *p = head_;
  360. while (p != NULL) {
  361. if (p->next_ != e)
  362. p = p->next_;
  363. else
  364. break;
  365. }
  366. assert(p != NULL);
  367. p->next_ = e->next_;
  368. if (tail_ == e)
  369. tail_ = p;
  370. size_--;
  371. if (size_ == 0) 
  372. assert((head_ == 0) && (tail_ == 0));
  373. }
  374.         QueueElem<T>* getHead() { return head_; }
  375. int is_empty() const { return (size_ == 0); }
  376. int size() const { return size_; }
  377. protected:
  378.         QueueElem<T> *head_, *tail_;
  379.         int size_;
  380. };
  381. //----------------------------------------------------------------------
  382. // Multimedia server
  383. //----------------------------------------------------------------------
  384. class MediaServer : public HttpServer {
  385. public:
  386. MediaServer();
  387. ~MediaServer();
  388. virtual AppData* get_data(int& size, AppData* d);
  389. protected:
  390. virtual int command(int argc, const char*const* argv);
  391. MediaSegment get_next_segment(MediaRequest *r, Application*& ci);
  392. // Prefetching list
  393. struct RegInfo {
  394. char name_[20];
  395. HttpApp* client_;
  396. };
  397. struct PrefInfo {
  398. MediaSegmentList* sl_;
  399. Application* conid_;
  400. };
  401. typedef Queue<PrefInfo> PrefInfoQ;
  402. typedef QueueElem<PrefInfo> PrefInfoE;
  403. PrefInfoE* find_prefinfo(PrefInfoQ* q, Application* conid) {
  404. for (PrefInfoE *e = q->getHead(); e != NULL; e = e->next())
  405. if (e->data()->conid_ == conid)
  406. return e;
  407. return NULL;
  408. }
  409. Tcl_HashTable *pref_; // Mapping <cache>:<pagenum> to PrefInfoQ
  410. Tcl_HashTable *cmap_; // Mapping MediaApps to clients
  411. PrefInfoQ* get_piq(const char* pgname, HttpApp* client) {
  412. PageID id;
  413. ClientPage::split_name(pgname, id);
  414. id.s_ = client;
  415. Tcl_HashEntry* he = 
  416. Tcl_FindHashEntry(pref_, (const char*)&id);
  417. if (he == NULL) 
  418. return NULL;
  419. return (PrefInfoQ*)Tcl_GetHashValue(he);
  420. }
  421. RegInfo* get_reginfo(Application* app) {
  422. Tcl_HashEntry *he = 
  423. Tcl_FindHashEntry(cmap_, (const char *)app);
  424. if (he == NULL) {
  425. fprintf(stderr, "Unknown connection!n");
  426. abort();
  427. return (RegInfo *)Tcl_GetHashValue(he);
  428. }
  429. };
  430. #endif // ns_mcache_h