Go to the documentation of this file.00001 
00008 
00009 
00010 
00011 
00012 
00013 #include <ecl/config/ecl.hpp>
00014 #if defined(ECL_IS_POSIX)
00015 
00016 
00017 
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 
00030 
00031 
00032 namespace ecl {
00033 namespace devices {
00034 
00035 
00036 
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 
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 
00065 
00066 
00067 Mutex SharedFileManager::mutex;
00068 std::map<string,SharedFileCommon*> SharedFileManager::opened_files;
00069 
00070 
00071 
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 
00082 
00083         iter->second->count += 1;
00084         shared_instance = iter->second;
00085     } else {
00086         
00087 
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 }; 
00125 
00126 
00127 
00128 
00129 
00130 using std::string;
00131 
00132 
00133 
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                 
00151                 
00152                 
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         
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 }; 
00215 
00216 #endif