FileDataStore.cxx
上传用户:sy_wanhua
上传日期:2013-07-25
资源大小:3048k
文件大小:11k
源码类别:

流媒体/Mpeg4/MP4

开发平台:

C/C++

  1. /* ====================================================================
  2.  * The Vovida Software License, Version 1.0 
  3.  * 
  4.  * Copyright (c) 2000 Vovida Networks, Inc.  All rights reserved.
  5.  * 
  6.  * Redistribution and use in source and binary forms, with or without
  7.  * modification, are permitted provided that the following conditions
  8.  * are met:
  9.  * 
  10.  * 1. Redistributions of source code must retain the above copyright
  11.  *    notice, this list of conditions and the following disclaimer.
  12.  * 
  13.  * 2. Redistributions in binary form must reproduce the above copyright
  14.  *    notice, this list of conditions and the following disclaimer in
  15.  *    the documentation and/or other materials provided with the
  16.  *    distribution.
  17.  * 
  18.  * 3. The names "VOCAL", "Vovida Open Communication Application Library",
  19.  *    and "Vovida Open Communication Application Library (VOCAL)" must
  20.  *    not be used to endorse or promote products derived from this
  21.  *    software without prior written permission. For written
  22.  *    permission, please contact vocal@vovida.org.
  23.  *
  24.  * 4. Products derived from this software may not be called "VOCAL", nor
  25.  *    may "VOCAL" appear in their name, without prior written
  26.  *    permission of Vovida Networks, Inc.
  27.  * 
  28.  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
  29.  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  30.  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
  31.  * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
  32.  * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
  33.  * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
  34.  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  35.  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  36.  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  37.  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  38.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
  39.  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  40.  * DAMAGE.
  41.  * 
  42.  * ====================================================================
  43.  * 
  44.  * This software consists of voluntary contributions made by Vovida
  45.  * Networks, Inc. and many individuals on behalf of Vovida Networks,
  46.  * Inc.  For more information on Vovida Networks, Inc., please see
  47.  * <http://www.vovida.org/>.
  48.  *
  49.  */
  50. static const char* const FileDataStore_cxx_Version =
  51.     "$Id: FileDataStore.cxx,v 1.13 2001/01/31 19:22:37 eddiem Exp $";
  52. #include <assert.h>
  53. #include <cerrno>
  54. #include <cstdio>
  55. #include "FileDataStore.hxx"
  56. #include "VIoException.hxx"
  57. FileDataStore::FileDataStore( int numBinsP, const string &fileRootP )
  58.         : DataStore(numBinsP * 200),
  59.         fileRoot(fileRootP),
  60.         numBins(numBinsP)
  61. {
  62.     assert( numBins < 1000 );
  63.     assert( numBins >= 0 );
  64.     assert( fileRoot.length() > 0 );
  65.     lock.WriteLock();
  66.     try
  67.     {
  68.         // check the root file system exists
  69.         if ( !VFileSystem::dirExists( fileRoot ) )
  70.         {
  71.             throw VIoException( strerror(errno),
  72.                                 __FILE__,
  73.                                 __LINE__,
  74.                                 errno );
  75.         }
  76.         // check all the groups dirs are created
  77.         for ( int bin = 0; bin < numBins; bin++ )
  78.         {
  79.             string dir = rootName( bin );
  80.             if ( !VFileSystem::dirExists( dir ) )
  81.             {
  82.                 VFileSystem::createDir( dir );
  83.             }
  84.         }
  85.     }
  86.     catch (...)
  87.     {
  88.         lock.Unlock();
  89.         throw;
  90.     }
  91.     lock.Unlock();
  92. }
  93. FileDataStore::~FileDataStore()
  94. {}
  95. string
  96. FileDataStore::getBin( int i ) const
  97. {
  98.     // This turns i into a 3 digit base 16 number and
  99.     // is prepresented with a A for 0, B for 1 ...
  100.     assert( i < 16*16*16 );
  101.     assert( i >= 0 );
  102.     int i3 = i % 16;
  103.     i = i / 16;
  104.     int i2 = i % 16;
  105.     i = i / 16;
  106.     int i1 = i % 16;
  107.     i = i / 16;
  108.     char c[4];
  109.     c[0] = 'A' + i1;
  110.     c[1] = 'A' + i2;
  111.     c[2] = 'A' + i3;
  112.     c[3] = 0;
  113.     string res(c);
  114.     return res;
  115. }
  116. string
  117. FileDataStore::getBin( const string& group, const string& name ) const
  118. {
  119.     int h = hash( group, name );
  120.     return getBin( h );
  121. }
  122. string
  123. FileDataStore::rootName( int bin ) const
  124. {
  125.     string ret = fileRoot;
  126.     if (numBins != 0)
  127.     {
  128.         ret += "/";
  129.         ret += getBin(bin);
  130.     }
  131.     return ret;
  132. }
  133. string
  134. FileDataStore::dirName(const string& group, const string& name ) const
  135. {
  136.     return dirName( group, hash(group, name) );
  137. }
  138. string
  139. FileDataStore::dirName(const string& group, int bin ) const
  140. {
  141.     string ret = rootName( bin );
  142.     ret += "/";
  143.     string g = group;
  144.     if ( numBins != 0 )
  145.     {
  146.         // flatten the group name - replace / with #
  147.         for (unsigned int i = 0; i < g.length(); i++)
  148.         {
  149.             if ( g[i] == '/' )
  150.             {
  151.                 g[i] = '#';
  152.             }
  153.         }
  154.     }
  155.     ret += g;
  156.     return ret;
  157. }
  158. string
  159. FileDataStore::fileName(const string& group, const string& name ) const
  160. {
  161.     string ret = dirName(group, name);
  162.     ret += "/";
  163.     ret += name;
  164.     ret += ".xml";
  165.     return ret;
  166. }
  167. int
  168. FileDataStore::hash(const string& group, const string& name ) const
  169. {
  170.     // There are no doubt better hashes but hey this looks like it will work
  171.     int h1 = 0;
  172.     int h2 = 0;
  173.     for ( unsigned int i = 0; i < name.length(); i++ )
  174.     {
  175.         h1 += name[i];
  176.         h2 += (h2 << 4) + name[i];
  177.     }
  178.     int h = (abs(h1 + h2)) % numBins;
  179.     assert( h >= 0 );
  180.     assert( h < numBins );
  181.     return h;
  182. }
  183. string
  184. FileDataStore::getItem( const string& group, const string& name )
  185. throw(VException&)
  186. {
  187.     string ret;
  188.     lock.ReadLock();
  189.     try
  190.     {
  191.         ret = VFileSystem::readFile( fileName(group, name) );
  192.     }
  193.     catch (...)
  194.     {
  195.         lock.Unlock();
  196.         throw;
  197.     }
  198.     lock.Unlock();
  199.     return ret;
  200. }
  201. TimeStamp
  202. FileDataStore::getItemTimeStamp( const string& group, const string& name )
  203. throw(VException&)
  204. {
  205.     TimeStamp ret;
  206.     lock.ReadLock();
  207.     try
  208.     {
  209.         ret = VFileSystem::getFileTime( fileName(group, name) );
  210.     }
  211.     catch (...)
  212.     {
  213.         lock.Unlock();
  214.         throw;
  215.     }
  216.     lock.Unlock();
  217.     return ret;
  218. }
  219. int
  220. FileDataStore::getItemSize( const string& group, const string& name )
  221. throw(VException&)
  222. {
  223.     int ret;
  224.     lock.ReadLock();
  225.     try
  226.     {
  227.         ret = VFileSystem::getFileSize( fileName(group, name) );
  228.     }
  229.     catch (...)
  230.     {
  231.         lock.Unlock();
  232.         throw;
  233.     }
  234.     lock.Unlock();
  235.     return ret;
  236. }
  237. void
  238. FileDataStore::putItem( const string& group,
  239.                         const string& name,
  240.                         const string& data,
  241.                         TimeStamp timeStamp)
  242. throw(VException&)
  243.     // timestamp defaults to 0
  244. {
  245.     if (!isGroup(group))
  246.     {
  247.         addGroup(group);
  248.     }
  249.     string fName( fileName(group, name) );
  250.     lock.WriteLock();
  251.     try
  252.     {
  253.         VFileSystem::writeFile( fName, data );
  254.         if (timeStamp != 0 )
  255.         {
  256.             VFileSystem::setFileTime( fName, timeStamp );
  257.         }
  258.     }
  259.     catch (...)
  260.     {
  261.         lock.Unlock();
  262.         throw;
  263.     }
  264.     lock.Unlock();
  265. }
  266. void
  267. FileDataStore::removeItem( const string& group, const string& name)
  268. throw(VException&)
  269. {
  270.     lock.WriteLock();
  271.     try
  272.     {
  273.         VFileSystem::removeFile( fileName(group, name) );
  274.     }
  275.     catch (...)
  276.     {
  277.         lock.Unlock();
  278.         throw;
  279.     }
  280.     lock.Unlock();
  281. }
  282. bool
  283. FileDataStore::isItem( const string& group, const string& name)
  284. throw(VException&)
  285. {
  286.     bool ret;
  287.     lock.ReadLock();
  288.     try
  289.     {
  290.         ret = VFileSystem::fileExists( fileName(group, name) );
  291.     }
  292.     catch (...)
  293.     {
  294.         lock.Unlock();
  295.         throw;
  296.     }
  297.     lock.Unlock();
  298.     return ret;
  299. }
  300. StringList
  301. FileDataStore::listItems(const string& group)
  302. throw(VException&)
  303. {
  304.     StringList list;
  305.     lock.ReadLock();
  306.     try
  307.     {
  308.         for ( int bin = 0; bin < numBins; bin++ )
  309.         {
  310.             StringList dirList( VFileSystem::readDir( dirName(group, bin) ));
  311.             StringList::iterator i = dirList.begin();
  312.             while ( i != dirList.end() )
  313.             {
  314.                 string s = *i;
  315.                 i++;
  316.                 // filter out "hidden" items in the directory
  317.                 static string cvs("CVS");
  318.                 if ( s == cvs ) continue;
  319.                 // strip .xml off end
  320.                 size_t location = s.rfind(".xml");
  321.                 if (location != string::npos)
  322.                 {
  323.                     string t = s.substr(0, location);
  324.                     list.push_back(t);
  325.                 }
  326.                 else
  327.                 {
  328.                     list.push_back(s);
  329.                 }
  330.             }
  331.         }
  332.     }
  333.     catch (...)
  334.     {
  335.         lock.Unlock();
  336.         throw;
  337.     }
  338.     lock.Unlock();
  339.     return list;
  340. }
  341. void
  342. FileDataStore::addGroup( const string& group )
  343. throw(VException&)
  344. {
  345.     lock.WriteLock();
  346.     try
  347.     {
  348.         for ( int bin = 0; bin < numBins; bin++ )
  349.         {
  350.             VFileSystem::createDir( dirName(group, bin) );
  351.         }
  352.     }
  353.     catch (...)
  354.     {
  355.         lock.Unlock();
  356.         throw;
  357.     }
  358.     lock.Unlock();
  359. }
  360. void
  361. FileDataStore::removeGroup( const string& group)
  362. throw(VException&)
  363. {
  364.     lock.WriteLock();
  365.     try
  366.     {
  367.         for ( int bin = 0; bin < numBins; bin++ )
  368.         {
  369.             VFileSystem::removeDir( dirName(group, bin) );
  370.         }
  371.     }
  372.     catch (...)
  373.     {
  374.         lock.Unlock();
  375.         throw;
  376.     }
  377.     lock.Unlock();
  378. }
  379. bool
  380. FileDataStore::isGroup( const string& group)
  381. throw(VException&)
  382. {
  383.     bool ret;
  384.     char err_buff[256];
  385.     lock.ReadLock();
  386.     try
  387.     {
  388.         ret = VFileSystem::dirExists( dirName(group, 0) );
  389. #ifndef NDEBUG
  390.         // check the groups exists in all bins
  391.         for ( int bin = 1; bin < numBins; bin++ )
  392.         {
  393.             bool v = VFileSystem::dirExists( dirName(group, bin) );
  394.             if ( v != ret )
  395.             {
  396.                 sprintf (err_buff, "Error: Number of hash bins has changed: %s",
  397.                          strerror(errno) );
  398.                 throw VIoException( err_buff,
  399.                                     __FILE__,
  400.                                     __LINE__,
  401.                                     errno );
  402.                 // We have an invalid group directory structure
  403.             }
  404.         }
  405. #endif
  406.     }
  407.     catch (...)
  408.     {
  409.         lock.Unlock();
  410.         throw;
  411.     }
  412.     lock.Unlock();
  413.     return ret;
  414. }
  415. StringList
  416. FileDataStore::listGroups()
  417. {
  418.     StringList ret;
  419.     if (numBins == 0 )
  420.     {
  421.         // this is not implemented - left as an exersise to the reader ...
  422.         // it would only be needed to upgrade old system to new
  423.         assert(0);
  424.     }
  425.     lock.ReadLock();
  426.     try
  427.     {
  428.         // loop over all the groups found in bin 0
  429.         StringList dirList( VFileSystem::readDir( rootName(0) ));
  430.         StringList::iterator i = dirList.begin();
  431.         while ( i != dirList.end() )
  432.         {
  433.             string s = *i;
  434.             i++;
  435.             // unflatten group names - replace # with /
  436.             for (unsigned int i = 0; i < s.length(); i++)
  437.             {
  438.                 if ( s[i] == '#' )
  439.                 {
  440.                     s[i] = '/';
  441.                 }
  442.             }
  443.             // filter out "hidden" items in the directory
  444.             static string cvs("CVS");
  445.             if ( s == cvs ) continue;
  446.             ret.push_back(s);
  447.         }
  448.     }
  449.     catch (...)
  450.     {
  451.         lock.Unlock();
  452.         throw;
  453.     }
  454.     lock.Unlock();
  455.     return ret;
  456. }