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 #include <ncbi_pch.hpp>
00033 #include <corelib/ncbifile.hpp>
00034 #include <corelib/plugin_manager_impl.hpp>
00035 #include <corelib/plugin_manager_store.hpp>
00036 #include <corelib/ncbifile.hpp>
00037
00038 #include <util/fileblobstorage/blobstorage_file.hpp>
00039 #include <util/error_codes.hpp>
00040
00041
00042 #define NCBI_USE_ERRCODE_X Util_BlobStore
00043
00044 BEGIN_NCBI_SCOPE
00045
00046
00047
00048
00049
00050 CBlobStorage_File::CBlobStorage_File(const string& storage_dir)
00051 {
00052 if (CDirEntry::IsAbsolutePath(storage_dir))
00053 m_StorageDir = storage_dir;
00054 else {
00055 m_StorageDir = CDir::GetCwd()
00056 + CDirEntry::GetPathSeparator()
00057 + storage_dir;
00058 }
00059 m_StorageDir = CDirEntry::NormalizePath(m_StorageDir);
00060
00061 CDir dir(m_StorageDir);
00062 if (!dir.Exists())
00063 if (!dir.CreatePath())
00064 NCBI_THROW(CBlobStorageException,
00065 eBusy, "Could not create a storage directory: " + m_StorageDir);
00066 }
00067
00068 CBlobStorage_File::CBlobStorage_File()
00069 {
00070 NCBI_THROW(CException, eInvalid,
00071 "Can not create an empty blob storage.");
00072 }
00073
00074
00075 CBlobStorage_File::~CBlobStorage_File()
00076 {
00077 try {
00078 Reset();
00079 } catch(exception& ex) {
00080 ERR_POST_X(1, "An exception caught in ~CBlobStorage_File() :" <<
00081 ex.what());
00082 } catch(...) {
00083 ERR_POST_X(2, "An unknown exception caught in ~CBlobStorage_File() :");
00084 }
00085 }
00086
00087 bool CBlobStorage_File::IsKeyValid(const string&)
00088 {
00089 return true;
00090 }
00091
00092 CNcbiIstream& CBlobStorage_File::GetIStream(const string& key,
00093 size_t* blob_size,
00094 ELockMode)
00095 {
00096 if (m_IStream.get())
00097 NCBI_THROW(CBlobStorageException,
00098 eBusy, "The input stream is in use.");
00099
00100 CFile blob(m_StorageDir + CDirEntry::GetPathSeparator() + key);
00101 if (!blob.Exists())
00102 NCBI_THROW(CBlobStorageException,
00103 eBlobNotFound, "Requested blob is not found. " + key);
00104
00105 Int8 fsize = blob.GetLength();
00106 m_IStream.reset(new CNcbiIfstream(blob.GetPath().c_str(),
00107 IOS_BASE::in | IOS_BASE::binary));
00108 if (!m_IStream->good() || fsize == -1 )
00109 NCBI_THROW(CBlobStorageException, eReader,
00110 "Reader couldn't create a temporary file. BlobKey: " + key);
00111
00112
00113 if (blob_size) *blob_size = (size_t)fsize;
00114 return *m_IStream;
00115 }
00116
00117 string CBlobStorage_File::GetBlobAsString(const string& data_id)
00118 {
00119 size_t bsize;
00120 CNcbiIstream& is = GetIStream(data_id, &bsize);
00121 string buf(bsize,0);
00122 is.read(&buf[0], bsize);
00123 m_IStream.reset();
00124 return buf;
00125 }
00126
00127 CNcbiOstream& CBlobStorage_File::CreateOStream(string& key,
00128 ELockMode)
00129
00130 {
00131 if (m_OStream.get())
00132 NCBI_THROW(CBlobStorageException,
00133 eBusy, "The output stream is in use.");
00134
00135 string fpath = CFile::GetTmpNameEx(m_StorageDir, kEmptyStr, CFile::eTmpFileCreate);
00136 m_OStream.reset(new CNcbiOfstream(fpath.c_str(), IOS_BASE::out | IOS_BASE::binary));
00137 if (!m_OStream->good())
00138 NCBI_THROW(CBlobStorageException,
00139 eWriter, "Writer couldn't create an ouput stream.");
00140 string dir, base, ext;
00141 CDirEntry::SplitPath(fpath, &dir, &base, &ext);
00142 key = base;
00143 if (!ext.empty())
00144 key += '.' + ext;
00145
00146 return *m_OStream;
00147 }
00148
00149 string CBlobStorage_File::CreateEmptyBlob()
00150 {
00151 string key;
00152 CreateOStream(key);
00153 m_OStream.reset();
00154 return key;
00155 }
00156
00157 void CBlobStorage_File::DeleteBlob(const string& data_id)
00158 {
00159 CFile blob(m_StorageDir + CDirEntry::GetPathSeparator() + data_id);
00160 if (blob.Exists())
00161 blob.Remove();
00162 }
00163
00164 void CBlobStorage_File::Reset()
00165 {
00166 m_IStream.reset();
00167 m_OStream.reset();
00168 }
00169
00170 void CBlobStorage_File::DeleteStorage()
00171 {
00172 CDir(m_StorageDir).Remove();
00173 }
00174
00175
00176
00177
00178
00179 const char* kBlobStorageFileDriverName = "fileblobstroage";
00180
00181
00182 class CBlobStorageFileCF
00183 : public CSimpleClassFactoryImpl<IBlobStorage,CBlobStorage_File>
00184 {
00185 public:
00186 typedef CSimpleClassFactoryImpl<IBlobStorage,
00187 CBlobStorage_File> TParent;
00188 public:
00189 CBlobStorageFileCF() : TParent(kBlobStorageFileDriverName, 0)
00190 {
00191 }
00192 virtual ~CBlobStorageFileCF()
00193 {
00194 }
00195
00196 virtual
00197 IBlobStorage* CreateInstance(
00198 const string& driver = kEmptyStr,
00199 CVersionInfo version = NCBI_INTERFACE_VERSION(IBlobStorage),
00200 const TPluginManagerParamTree* params = 0) const;
00201 };
00202
00203 IBlobStorage* CBlobStorageFileCF::CreateInstance(
00204 const string& driver,
00205 CVersionInfo version,
00206 const TPluginManagerParamTree* params) const
00207 {
00208 if (driver.empty() || driver == m_DriverName) {
00209 if (version.Match(NCBI_INTERFACE_VERSION(IBlobStorage))
00210 != CVersionInfo::eNonCompatible && params) {
00211
00212 string storage_dir =
00213 GetParam(params, "storage_dir", false, ".");
00214 return new CBlobStorage_File(storage_dir);
00215 }
00216 }
00217 return 0;
00218 }
00219
00220 void NCBI_EntryPoint_xblobstorage_file(
00221 CPluginManager<IBlobStorage>::TDriverInfoList& info_list,
00222 CPluginManager<IBlobStorage>::EEntryPointRequest method)
00223 {
00224 CHostEntryPointImpl<CBlobStorageFileCF>
00225 ::NCBI_EntryPointImpl(info_list, method);
00226 }
00227
00228 void BlobStorage_RegisterDriver_File(void)
00229 {
00230 RegisterEntryPoint<IBlobStorage>( NCBI_EntryPoint_xblobstorage_file );
00231 }
00232
00233 END_NCBI_SCOPE
00234
00235