$search
00001 00008 /***************************************************************************** 00009 ** Cross Platform Functionality 00010 *****************************************************************************/ 00011 // Only because there is only ofile_pos support so far. 00012 00013 #include <ecl/config/ecl.hpp> 00014 #if defined(ECL_IS_POSIX) 00015 00016 /***************************************************************************** 00017 ** Includes 00018 *****************************************************************************/ 00019 00020 #include <iostream> 00021 #include <map> 00022 #include <string> 00023 #include <ecl/errors/handlers.hpp> 00024 #include <ecl/exceptions/standard_exception.hpp> 00025 #include <ecl/exceptions/macros.hpp> 00026 #include "../../include/ecl/devices/shared_file.hpp" 00027 00028 /***************************************************************************** 00029 ** Namespaces 00030 *****************************************************************************/ 00031 00032 namespace ecl { 00033 namespace devices { 00034 00035 /**************************************************************************** 00036 ** Using 00037 *****************************************************************************/ 00038 00039 using std::string; 00040 using ecl::WriteMode; 00041 using ecl::CloseError; 00042 using ecl::StandardException; 00043 using ecl::Mutex; 00044 00045 /***************************************************************************** 00046 ** Implementation [SharedFileCommon] 00047 *****************************************************************************/ 00048 00049 SharedFileCommon::SharedFileCommon(const std::string &name, ecl::WriteMode mode) ecl_throw_decl(StandardException) : 00050 count(1), 00051 error_handler(NoError) 00052 { 00053 ecl_try { 00054 if ( !file.open(name,mode) ) { 00055 error_handler = file.error(); 00056 } 00057 } ecl_catch( StandardException &e ) { 00058 error_handler = file.error(); 00059 ecl_throw(StandardException(LOC,e)); 00060 } 00061 } 00062 00063 /***************************************************************************** 00064 ** Static Variable Initialisation [SharedFileManager] 00065 *****************************************************************************/ 00066 00067 Mutex SharedFileManager::mutex; 00068 std::map<string,SharedFileCommon*> SharedFileManager::opened_files; 00069 00070 /***************************************************************************** 00071 ** Implementation [SharedFileManager] 00072 *****************************************************************************/ 00073 00074 SharedFileCommon* SharedFileManager::RegisterSharedFile(const std::string& name, ecl::WriteMode mode) ecl_throw_decl(StandardException) { 00075 00076 mutex.lock(); 00077 std::map<std::string,SharedFileCommon*>::iterator iter = opened_files.find(name); 00078 SharedFileCommon* shared_instance; 00079 if ( iter != opened_files.end() ) { 00080 /****************************************** 00081 ** File exists - do not open 00082 *******************************************/ 00083 iter->second->count += 1; 00084 shared_instance = iter->second; 00085 } else { 00086 /****************************************** 00087 ** File does not exist - open it 00088 *******************************************/ 00089 ecl_try { 00090 shared_instance = new SharedFileCommon(name,mode); 00091 opened_files.insert(std::pair<string,SharedFileCommon*>(name,shared_instance)); 00092 } ecl_catch ( StandardException &e ) { 00093 shared_instance = NULL; 00094 ecl_throw(StandardException(LOC,e)); 00095 } 00096 } 00097 mutex.unlock(); 00098 return shared_instance; 00099 } 00105 bool SharedFileManager::DeRegisterSharedFile(const std::string& name) ecl_throw_decl(StandardException) { 00106 00107 mutex.lock(); 00108 std::map<std::string,SharedFileCommon*>::iterator iter = opened_files.find(name); 00109 00110 if ( iter == opened_files.end() ) { 00111 ecl_throw(StandardException(LOC,CloseError,"The specified shared object file could not be closed - was not found.")); 00112 return false; 00113 } 00114 if ( iter->second->count == 1 ) { 00115 delete iter->second; 00116 opened_files.erase(iter); 00117 } else { 00118 iter->second->count -= 1; 00119 } 00120 mutex.unlock(); 00121 return true; 00122 } 00123 00124 }; // namespace Interfaces 00125 00126 /***************************************************************************** 00127 ** Using 00128 *****************************************************************************/ 00129 00130 using std::string; 00131 00132 /***************************************************************************** 00133 ** Implementation [SharedFile] 00134 *****************************************************************************/ 00135 00136 SharedFile::SharedFile(const std::string &name, WriteMode mode) ecl_throw_decl(StandardException) : 00137 shared_instance(NULL) 00138 { 00139 ecl_try { 00140 open(name,mode); 00141 } ecl_catch( StandardException &e ) { 00142 ecl_throw(StandardException(LOC,e)); 00143 } 00144 } 00145 00146 SharedFile::~SharedFile() { 00147 ecl_try { 00148 devices::SharedFileManager::DeRegisterSharedFile( shared_instance->file.filename() ); 00149 } ecl_catch( StandardException &e ) { 00150 // Never throw from a destructor! 00151 // use some other mechanism!!! 00152 // throw StandardException(LOC,e); 00153 } 00154 } 00155 00156 bool SharedFile::open(const std::string &name, WriteMode mode) ecl_throw_decl(StandardException) { 00157 ecl_try { 00158 shared_instance = devices::SharedFileManager::RegisterSharedFile(name,mode); 00159 if ( shared_instance == NULL ) { 00160 shared_instance->error_handler = OpenError; 00161 return false; 00162 } else { 00163 shared_instance->error_handler = NoError; 00164 return true; 00165 } 00166 } ecl_catch ( StandardException &e ) { 00167 shared_instance->error_handler = OpenError; 00168 ecl_throw(StandardException(LOC,e)); 00169 } 00170 } 00171 00172 long SharedFile::write(const char &c) ecl_debug_throw_decl(StandardException) { 00173 long n = buffer.append(c); 00174 if ( buffer.full() ) { 00175 if ( !flush() ) { 00176 return -1; 00177 } 00178 } 00179 return n; 00180 } 00181 00182 long SharedFile::write(const char* s, unsigned long n) ecl_debug_throw_decl(StandardException) { 00183 unsigned int no_written = 0; 00184 while ( no_written < n ) { 00185 no_written += buffer.append(s+no_written,n-no_written); 00186 if ( buffer.full() ) { 00187 if ( !flush() ) { 00188 return -1; 00189 } 00190 } 00191 } 00192 return n; 00193 } 00194 00195 bool SharedFile::flush() ecl_debug_throw_decl(StandardException) { 00196 long written; 00197 ecl_debug_try { 00198 written = shared_instance->file.write(buffer.c_ptr(), buffer.size() ); 00199 } ecl_debug_catch(const StandardException &e) { 00200 shared_instance->error_handler = shared_instance->file.error(); 00201 ecl_throw(StandardException(LOC,e)); 00202 } 00203 buffer.clear(); 00204 // fallback for no exceptions 00205 shared_instance->error_handler = shared_instance->file.error(); 00206 if ( written > 0 ) { 00207 return true; 00208 } else { 00209 return false; 00210 } 00211 } 00212 00213 00214 }; // namespace ecl 00215 00216 #endif /* ECL_IS_POSIX */