Back to index

nordugrid-arc-nox  1.1.0~rc6
PayloadFile.cpp
Go to the documentation of this file.
00001 #ifdef HAVE_CONFIG_H
00002 #include <config.h>
00003 #endif
00004 
00005 #include <sys/types.h>
00006 #include <sys/stat.h>
00007 #include <unistd.h>
00008 #include <fcntl.h>
00009 #ifndef WIN32 
00010 #include <sys/mman.h>
00011 #endif
00012 #include <iostream>
00013 #include "PayloadFile.h"
00014 
00015 namespace ARex {
00016 
00017 PayloadBigFile::Size_t PayloadBigFile::threshold_ = 1024*1024*10; // 10MB by default
00018 
00019 PayloadFile::PayloadFile(const char* filename,Size_t start,Size_t end) {
00020   handle_=::open(filename,O_RDONLY);
00021   SetRead(handle_,start,end);
00022 }
00023 
00024 PayloadFile::PayloadFile(int h,Size_t start,Size_t end) {
00025   SetRead(h,start,end);
00026 }
00027 
00028 void PayloadFile::SetRead(int h,Size_t start,Size_t end) {
00029   handle_=h;
00030   start_=start;
00031   end_=end;
00032   addr_=NULL;
00033   size_=0;
00034   if(handle_ == -1) return;
00035   struct stat st;
00036   if(fstat(handle_,&st) != 0) goto error;
00037   size_=st.st_size;
00038   if(end_ > size_) {
00039     end_=size_;
00040   }
00041   if(start_ >= size_) {
00042     start_=size_;
00043     end_=start_;
00044     return;
00045   }
00046 
00047 #ifndef WIN32 
00048   if(size_ > 0) {
00049     addr_=(char*)mmap(NULL,size_,PROT_READ,MAP_SHARED,handle_,0);
00050     if(addr_ == MAP_FAILED) goto error;
00051   }
00052 #else 
00053   goto error;
00054 #endif
00055 
00056   return;
00057 error:
00058   perror("PayloadFile");
00059   if(handle_ != -1) ::close(handle_);
00060   handle_=-1; size_=0; addr_=NULL;
00061   return;
00062 }
00063 
00064 PayloadFile::~PayloadFile(void) {
00065 
00066 #ifndef WIN32 
00067   if(addr_ != NULL) munmap(addr_,size_);
00068 #endif
00069 
00070   ::close(handle_);
00071   handle_=-1; size_=0; addr_=NULL;
00072   return;
00073 }
00074 
00075 char* PayloadFile::Content(Size_t pos) {
00076   if(handle_ == -1) return NULL;
00077   if(pos >= end_) return NULL;
00078   if(pos < start_) return NULL;
00079   return (addr_+pos);
00080 }
00081 
00082 char PayloadFile::operator[](Size_t pos) const {
00083   if(handle_ == -1) return 0;
00084   if(pos >= end_) return 0;
00085   if(pos < start_) return 0;
00086   return addr_[pos];
00087 }
00088 
00089 PayloadFile::Size_t PayloadFile::Size(void) const {
00090   return size_;
00091 }
00092 
00093 char* PayloadFile::Insert(Size_t /*pos*/,Size_t /*size*/) {
00094   // Not supported
00095   return NULL;
00096 }
00097 
00098 char* PayloadFile::Insert(const char*,Size_t /*pos*/,Size_t /*size*/) {
00099   // Not supported
00100   return NULL;
00101 }
00102 
00103 char* PayloadFile::Buffer(unsigned int num) {
00104   if(handle_ == -1) return NULL;
00105   if(num>0) return NULL;
00106   if(addr_ == NULL) return NULL;
00107   return addr_+start_;
00108 }
00109 
00110 PayloadFile::Size_t PayloadFile::BufferSize(unsigned int num) const {
00111   if(handle_ == -1) return 0;
00112   if(num>0) return 0;
00113   return (end_-start_);
00114 }
00115 
00116 PayloadFile::Size_t PayloadFile::BufferPos(unsigned int num) const {
00117   if(num == 0) return start_;
00118   return end_;
00119 }
00120 
00121 bool PayloadFile::Truncate(Size_t /*size*/) {
00122   // Not supported
00123   return false;
00124 }
00125 
00126 static int open_file_read(const char* filename) {
00127   return ::open(filename,O_RDONLY);
00128 }
00129 
00130 static int open_file_write(const char* filename) {
00131   return ::open(filename,O_WRONLY | O_CREAT,S_IRUSR | S_IWUSR);
00132 }
00133 
00134 PayloadBigFile::PayloadBigFile(int h,Size_t start,Size_t end):
00135                        PayloadStream(h) {
00136   seekable_ = false;
00137   if(handle_ == -1) return;
00138   ::lseek(handle_,start,SEEK_SET);
00139   limit_ = end;
00140 }
00141 
00142 PayloadBigFile::PayloadBigFile(const char* filename,Size_t start,Size_t end):
00143                        PayloadStream(open_file_read(filename)) {
00144   seekable_ = false;
00145   if(handle_ == -1) return;
00146   ::lseek(handle_,start,SEEK_SET);
00147   limit_ = end;
00148 }
00149 
00150 //PayloadBigFile::PayloadBigFile(const char* filename,Size_t size):
00151 //                       PayloadStream(open_file_write(filename)){
00152 //  seekable_ = false;
00153 //}
00154 
00155 PayloadBigFile::~PayloadBigFile(void) {
00156   if(handle_ != -1) ::close(handle_);
00157 }
00158 
00159 Arc::PayloadStream::Size_t PayloadBigFile::Pos(void) const {
00160   if(handle_ == -1) return 0;
00161   return ::lseek(handle_,0,SEEK_CUR);
00162 }
00163 
00164 Arc::PayloadStream::Size_t PayloadBigFile::Size(void) const {
00165   if(handle_ == -1) return 0;
00166   struct stat st;
00167   if(fstat(handle_,&st) != 0) return 0;
00168   return st.st_size;
00169 }
00170 
00171 Arc::PayloadStream::Size_t PayloadBigFile::Limit(void) const {
00172   Size_t s = Size();
00173   if((limit_ == (size_t)(-1)) || (limit_ > s)) return s;
00174   return limit_;
00175 }
00176 
00177 bool PayloadBigFile::Get(char* buf,int& size) {
00178   if(handle_ == -1) return false;
00179   if(limit_ == (size_t)(-1)) return PayloadStream::Get(buf,size);
00180   Size_t cpos = Pos();
00181   if(cpos >= limit_) {
00182     size=0; return false;
00183   }
00184   if((cpos+size) > limit_) size=limit_-cpos;
00185   return PayloadStream::Get(buf,size);
00186 }
00187 
00188 Arc::MessagePayload* newFileRead(const char* filename,Arc::PayloadRawInterface::Size_t start,Arc::PayloadRawInterface::Size_t end) {
00189   int h = open_file_read(filename);
00190   return newFileRead(h,start,end);
00191 }
00192 
00193 Arc::MessagePayload* newFileRead(int h,Arc::PayloadRawInterface::Size_t start,Arc::PayloadRawInterface::Size_t end) {
00194 #ifndef WIN32 
00195   struct stat st;
00196   if(fstat(h,&st) != 0) return NULL;
00197   if(st.st_size > PayloadBigFile::Threshold()) {
00198     PayloadBigFile* f = new PayloadBigFile(h,start,end);
00199     if(!*f) { delete f; return NULL; };
00200     return f;
00201   } else {
00202     PayloadFile* f = new PayloadFile(h,start,end);
00203     if(!*f) { delete f; return NULL; };
00204     return f;
00205   };
00206 #else
00207   PayloadBigFile* f = new PayloadBigFile(h,start,end);
00208   if(!*f) { delete f; return NULL; };
00209   return f;
00210 #endif
00211 }
00212 
00213 } // namespace ARex
00214