DocumentStorage.cpp
上传用户:xqtpzdz
上传日期:2022-05-21
资源大小:1764k
文件大小:6k
源码类别:

xml/soap/webservice

开发平台:

Visual C++

  1. /****************License************************************************
  2.  * Vocalocity OpenVXI
  3.  * Copyright (C) 2004-2005 by Vocalocity, Inc. All Rights Reserved.
  4.  * This program is free software; you can redistribute it and/or
  5.  * modify it under the terms of the GNU General Public License
  6.  * as published by the Free Software Foundation; either version 2
  7.  * of the License, or (at your option) any later version.
  8.  *  
  9.  * This program is distributed in the hope that it will be useful,
  10.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  * GNU General Public License for more details.
  13.  *
  14.  * You should have received a copy of the GNU General Public License
  15.  * along with this program; if not, write to the Free Software
  16.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  17.  * Vocalocity, the Vocalocity logo, and VocalOS are trademarks or 
  18.  * registered trademarks of Vocalocity, Inc. 
  19.  * OpenVXI is a trademark of Scansoft, Inc. and used under license 
  20.  * by Vocalocity.
  21.  ***********************************************************************/
  22. #include "DocumentStorage.hpp"
  23. #include "md5.h"
  24. DocumentStorageSingleton * DocumentStorageSingleton::ds = NULL;
  25. unsigned long DocumentStorageSingleton::maxBytes = 1024*1024; 
  26. // ------*---------*---------*---------*---------*---------*---------*---------
  27. // About GreedyDual caching
  28. //
  29. // This is a simple functions with the following desirable characteristics.
  30. //  * Recently accessed items remain for a time
  31. //  * Frequently accessed items tend to remain in cache
  32. //  * Very few parameters are required and the computational cost is small
  33. // 
  34. // Initialize the limit, L, to 0.
  35. // For every document, d:
  36. //
  37. //   1. If d is in memory, set H(p) = L + c(p)
  38. //   2. If d is not in memory
  39. //      a. While there is not room, set L to the lowest score and delete
  40. //         documents having that score.
  41. //      b. Store d in memory and set H(d) = L + c(p)
  42. //
  43. // ------*---------*---------*---------*---------*---------*---------*---------
  44. void DocumentStorageSingleton::Initialize(unsigned int cacheSize)
  45. {
  46.   DocumentStorageSingleton::ds = new DocumentStorageSingleton(); 
  47.   DocumentStorageSingleton::maxBytes = cacheSize * 1024; // max buffer allowed for memory cache
  48. }
  49. void DocumentStorageSingleton::Deinitialize()
  50. { delete DocumentStorageSingleton::ds; }
  51. void DocumentStorageSingleton::Store(VXMLDocument & doc,
  52.                                      const VXIbyte * buffer,
  53.                                      VXIulong bufSize,
  54.                                      const VXIchar * url)
  55. {
  56.   // Handle the case where the memory cache is disabled.
  57.   if (bufSize > maxBytes) return;
  58.   // Generate key.
  59.   DocumentStorageKey key = GenerateKey(buffer, bufSize, url);
  60.   VXItrdMutexLock(mutex);
  61.   DOC_STORAGE::iterator i = storage.find(key);
  62.   // Cache does not exist, try to cache it
  63.   if (i == storage.end()) {
  64.     while ((totalBytes + bufSize > maxBytes) && !storage.empty()) {
  65.       // Buffer is full.
  66.       DOC_STORAGE::iterator minIterator = storage.begin();
  67.       unsigned long minScore = (*minIterator).second.GetScore();
  68.       // The algorithm needed to improve, right now it just find the smallest size
  69.       for (DOC_STORAGE::iterator i = storage.begin(); i != storage.end(); ++i) {
  70.         if ((*i).second.GetScore() > minScore) continue;
  71.         minScore = (*i).second.GetScore();
  72.         minIterator = i;
  73.       }
  74.       
  75.       // remove the oldest entry that is found      
  76.       if ( minIterator != storage.end() ) {
  77.         // adjust current total bytes
  78.         totalBytes -= (*minIterator).second.GetSize();
  79.         storage.erase(minIterator);
  80.       }
  81.       // Note: In a two level cache, this document might be written to disk before
  82.       // being flushed from memory.
  83.     }
  84.   
  85.     storage[key] = DocumentStorageRecord(doc, bufSize, GreedyDualL);
  86.     // Add size of the cache to keep track of total size of all entries
  87.     totalBytes += bufSize;
  88.   }
  89.   VXItrdMutexUnlock(mutex);
  90. }
  91. bool DocumentStorageSingleton::Retrieve(VXMLDocument & doc,
  92.                                         const VXIbyte * buffer,
  93.                                         VXIulong bufSize,
  94.                                         const VXIchar * url)
  95. {
  96.   // Handle the case where the memory cache is disabled.
  97.   if (bufSize > maxBytes) return false;
  98.   bool result = false;
  99.   VXItrdMutexLock(mutex);
  100.   DOC_STORAGE::iterator i = storage.find(GenerateKey(buffer, bufSize, url));
  101.   if (i != storage.end()) {
  102.     try {
  103.       doc = (*i).second.GetDoc(GreedyDualL);
  104.       result = true;
  105.     } 
  106.     catch (...) {
  107.       // The cached document has been corrupted, remove it 
  108.       // and adjust current total bytes
  109.       totalBytes -= (*i).second.GetSize();
  110.       storage.erase(i);
  111.       result = false;        
  112.     }
  113.   }
  114.   if (result == false) {
  115.     // Note: In a two level cache scheme, this is where the data would be read
  116.     //       back from disk.  In this one level implementation, no action is
  117.     //       performed.
  118.   }
  119.   VXItrdMutexUnlock(mutex);
  120.   return result;
  121. }
  122. DocumentStorageKey DocumentStorageSingleton::GenerateKey(const VXIbyte * buf,
  123.                                                          VXIulong bufSize,
  124.                                                          const VXIchar * url)
  125. {
  126.   // Create a MD5 digest for the key
  127.   MD5_CTX md5;
  128.   DocumentStorageKey temp;
  129.   
  130.   // Generate first key
  131.   MD5Init (&md5);
  132.   MD5Update (&md5, buf, bufSize);
  133.   MD5Final (temp.raw, &md5);
  134.   
  135.   // Generate second key if applicable
  136.   if( url != NULL ) {
  137.     VXIulong urlLen = wcslen(url) * sizeof(VXIchar) / sizeof(VXIbyte);
  138.     MD5Init (&md5);
  139.     MD5Update (&md5, reinterpret_cast<const VXIbyte*>(url), urlLen);
  140.     MD5Final (&(temp.raw[16]), &md5);       
  141.   }
  142.   return temp;
  143. }