00001
00002
00003
00004
00005
00006
00007
00008 #include "ibrcommon/data/BLOB.h"
00009 #include "ibrcommon/thread/MutexLock.h"
00010 #include "ibrcommon/Exceptions.h"
00011 #include <stdio.h>
00012 #include <stdlib.h>
00013
00014 namespace ibrcommon
00015 {
00016 File BLOB::tmppath;
00017
00018 BLOB::BLOB(std::iostream &stream)
00019 : _stream(stream), _refcount(0)
00020 { }
00021
00022 BLOB::~BLOB()
00023 {
00024 }
00025
00026 BLOB::Reference::Reference(const Reference &ref)
00027 : _blob(ref._blob)
00028 {
00029 _blob->increment();
00030 }
00031
00032 BLOB::Reference::~Reference()
00033 {
00034 _blob->decrement();
00035 if (_blob->isUnbound())
00036 {
00037 delete _blob;
00038 }
00039 }
00040
00041 std::iostream& BLOB::Reference::operator* ()
00042 {
00043 return _blob->_stream;
00044 }
00045
00046 BLOB::Reference::Reference(BLOB *blob)
00047 : _blob(blob)
00048 {
00049 _blob->increment();
00050 }
00051
00052 void BLOB::Reference::enter()
00053 {
00054
00055 _blob->enter();
00056
00057
00058 (**this).clear();
00059 (**this).seekp(0);
00060 (**this).seekg(0);
00061 }
00062
00063 void BLOB::Reference::leave()
00064 {
00065
00066 (**this).clear();
00067
00068
00069 (**this).seekp(0);
00070 (**this).seekg(0);
00071
00072
00073 _blob->leave();
00074 }
00075
00076 size_t BLOB::Reference::getSize() const
00077 {
00078 return _blob->getSize();
00079 }
00080
00081 void BLOB::Reference::clear()
00082 {
00083 _blob->clear();
00084 }
00085
00086 void BLOB::increment()
00087 {
00088 MutexLock l(_reflock);
00089 _refcount++;
00090 }
00091
00092 void BLOB::decrement()
00093 {
00094 MutexLock l(_reflock);
00095 _refcount--;
00096 }
00097
00098 bool BLOB::isUnbound()
00099 {
00100 MutexLock l(_reflock);
00101 if (_refcount == 0) return true;
00102 return false;
00103 }
00104
00105 size_t BLOB::getSize() const
00106 {
00107
00108 size_t pos = _stream.tellg();
00109
00110 _stream.seekg(0, std::ios_base::end);
00111 size_t size = _stream.tellg();
00112 _stream.seekg(pos);
00113
00114 return size;
00115 }
00116
00117 BLOB::Reference StringBLOB::create()
00118 {
00119 BLOB::Reference ref(new StringBLOB());
00120 return ref;
00121 }
00122
00123 void StringBLOB::clear()
00124 {
00125 _stringstream.str("");
00126 }
00127
00128 StringBLOB::StringBLOB()
00129 : BLOB(_stringstream), _stringstream()
00130 {
00131
00132 }
00133
00134 StringBLOB::~StringBLOB()
00135 {
00136 }
00137
00138 BLOB::Reference FileBLOB::create(const File &f)
00139 {
00140 BLOB::Reference ref(new FileBLOB(f));
00141 return ref;
00142 }
00143
00144 void FileBLOB::clear()
00145 {
00146 throw ibrcommon::IOException("clear is not possible on a read only file");
00147 }
00148
00149 FileBLOB::FileBLOB(const File &f)
00150 : BLOB(_filestream), _filestream(), _file(f)
00151 {
00152 if (!f.exists())
00153 {
00154 throw ibrcommon::FileNotExistsException(f);
00155 }
00156
00157
00158 _filestream.open(f.getPath().c_str(), ios::in|ios::binary);
00159
00160 if (!_filestream.is_open())
00161 {
00162 throw ibrcommon::CanNotOpenFileException(f);
00163 }
00164 }
00165
00166 FileBLOB::~FileBLOB()
00167 {
00168
00169 _filestream.close();
00170 }
00171
00172 BLOB::Reference TmpFileBLOB::create()
00173 {
00174 try {
00175 BLOB::Reference ref(new TmpFileBLOB());
00176 return ref;
00177 } catch (ibrcommon::IOException ex) {
00178 return StringBLOB::create();
00179 }
00180 }
00181
00182 void TmpFileBLOB::clear()
00183 {
00184 enter();
00185 _filestream.close();
00186 _tmpfile.remove();
00187 _filestream.open(_tmpfile.getPath().c_str(), ios::in|ios::out|ios::binary|ios::trunc);
00188 leave();
00189 }
00190
00191 TmpFileBLOB::TmpFileBLOB()
00192 : BLOB(_filestream), _filestream()
00193 {
00194
00195 if (!BLOB::tmppath.isDirectory())
00196 {
00197 throw ibrcommon::IOException("BLOB::tmppath not initialized or path is not a directory.");
00198 }
00199
00200
00201 _tmpfile = getTmpFile();
00202
00203
00204 _filestream.open(_tmpfile.getPath().c_str(), ios::in|ios::out|ios::binary|ios::trunc);
00205 _tmpfile.update();
00206
00207 if (!_filestream.is_open())
00208 {
00209 throw ibrcommon::CanNotOpenFileException(_tmpfile);
00210 }
00211 }
00212
00213 File TmpFileBLOB::getTmpFile()
00214 {
00215 char *name;
00216
00217 if ( (name = tempnam( BLOB::tmppath.getPath().c_str(), NULL )) == NULL )
00218 throw ibrcommon::IOException("Could not create a temporary name.");
00219
00220 string filename(name);
00221 free(name);
00222
00223 return File(filename);
00224 }
00225
00226 TmpFileBLOB::~TmpFileBLOB()
00227 {
00228
00229 _filestream.close();
00230
00231
00232 _tmpfile.remove();
00233 }
00234 }