00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "RioFile.h"
00019
00020 #include "RioMMObject.h"
00021 #include "RioError.h"
00022
00023 #include <string.h>
00024 #include <stdlib.h>
00025 #include <stdio.h>
00026 #include <fcntl.h>
00027 #include <unistd.h>
00028 #include <pthread.h>
00029 #include <iostream>
00030 #include <errno.h>
00031 using namespace std;
00032
00033 RioFile::RioFile( const char *filename, unsigned int blocksize )
00034 {
00035 CurrentBlock = 0;
00036 TotalBlocks = 0;
00037 BlockSize = blocksize;
00038
00039 Request.Size = BlockSize;
00040 Request.Buffer = new char[ BlockSize ];
00041 Request.User = (void*)0;
00042 Request.Who = this;
00043 Request.CallBackFunction = RioFile::CallBack;
00044 BufferStatus = BUFFEREMPTY;
00045
00046 strcpy( RemoteFilename, filename );
00047 LocalFilename[ 0 ] = '\0';
00048 HasLocal = false;
00049 }
00050
00051 RioFile::~RioFile( void )
00052 {
00053 delete (char *)(Request.Buffer);
00054 Close();
00055 }
00056
00057
00058
00059 int RioFile::Open( RioAccess Access, CRioStream *Stream )
00060 {
00061 int rc;
00062
00063 #ifdef RIO_DEBUG2
00064 RioErr << "[RioFile]: Entrando na Open (" << RemoteFilename << ")"
00065 << endl;
00066 #endif
00067
00068 rc = Object.Open( RemoteFilename, Access, Stream );
00069 if( rc >= 0 )
00070 {
00071
00072 rc = Object.GetSize( &ObjSize );
00073 TotalBlocks = (int)(( (ObjSize - 1)/BlockSize ) + 1);
00074 }
00075 #ifdef RIO_DEBUG2
00076 else
00077 {
00078 RioErr << "Could not open file (" << RemoteFilename << ")" << endl;
00079 }
00080 #endif
00081
00082 #ifdef RIO_DEBUG2
00083 RioErr << "[RioFile]: Saindo da Open" << endl;
00084 #endif
00085
00086 return( rc );
00087 }
00088
00089 int RioFile::Close( void )
00090 {
00091 CRioStream *Stream;
00092
00093 Stream = Object.GetObjectStream();
00094
00095 if( HasLocal )
00096 Delete();
00097
00098 return( Object.Close() );
00099 }
00100
00101
00102
00103
00104
00105 void RioFile::Download( const char *dest_name )
00106 {
00107 RioBlock block;
00108 int tempfd = 0;
00109 int escritos;
00110
00111 #ifdef RIO_DEBUG2
00112 RioErr << "[RioFile]: Entrando na Download" << endl;
00113 #endif
00114
00115 if( strcmp( dest_name, "" ) != 0 )
00116 {
00117 strcpy( LocalFilename, dest_name );
00118
00119 if( (tempfd = open( LocalFilename, O_RDWR|O_CREAT, 0600 ) ) == -1 )
00120 {
00121 RioErr << "\tError generating temporary file for remote object."
00122 << endl;
00123 abort( );
00124 }
00125 }
00126 else
00127 {
00128 strcpy( LocalFilename, "/tmp/riommclientXXXXXX" );
00129
00130 if( (tempfd = mkstemp( LocalFilename )) == -1 )
00131 {
00132 RioErr << "\tError generating temporary file for remote object."
00133 << endl;
00134 abort( );
00135 }
00136 }
00137 HasLocal = true;
00138
00139 #ifdef RIO_DEBUG2
00140 RioErr << "[RioFile]: Download() - Created temporary file" << endl;
00141 #endif
00142
00143 block = 0;
00144 Request.Result = S_OK;
00145 Request.Who = this;
00146
00147 pthread_mutex_init( &Mutex, NULL );
00148 pthread_cond_init( &Condition, NULL );
00149
00150 #ifdef RIO_DEBUG2
00151 RioErr << "[RioFile]: Download() - Downloading..." << endl;
00152 #endif
00153
00154 while( block < TotalBlocks )
00155 {
00156 BufferStatus = BUFFEREMPTY;
00157
00158 Request.Block = block;
00159 Request.Status = RIO_REQUEST_FREE;
00160
00161 RioResult hResult = Object.StreamRead( &Request, UNICASTTRAFFIC );
00162 if( FAILED( hResult ) )
00163 {
00164 RioErr << "\tUnexpected RioFile error while reading object."
00165 << endl;
00166 abort();
00167 }
00168
00169 #ifdef RIO_DEBUG2
00170 RioErr << "[RioFile]: Download() - Waiting on mutex..." << endl;
00171 #endif
00172
00173 pthread_mutex_lock( &Mutex );
00174
00175 #ifdef RIO_DEBUG2
00176 RioErr << "[RioFile]: Download() - Acquired mutex..." << endl;
00177 RioErr << "[RioFile]: Download() - Waiting condition... "
00178 << RemoteFilename << endl;
00179 #endif
00180
00181
00182
00183
00184
00185 while( BufferStatus == BUFFEREMPTY )
00186 pthread_cond_wait( &Condition, &Mutex );
00187
00188 #ifdef RIO_DEBUG2
00189 RioErr << "[RioFile]: Download() - Condition is valid..." << endl;
00190 #endif
00191
00192 if( block < TotalBlocks-1 )
00193 {
00194 escritos = write( tempfd, Request.Buffer, BlockSize );
00195
00196 if( escritos != (int) BlockSize )
00197 {
00198 RioErr << "RioFile::Download erro ao escrever o valor de "
00199 << "Request.Buffer: escritos "<< escritos << " bytes "
00200 << "de um total de " << BlockSize << " bytes."
00201 << endl;
00202 }
00203 else if( escritos == -1 )
00204 {
00205 RioErr << "RioFile::Download erro " << errno << "("
00206 << strerror( errno ) << ") ao escrever o valor de "
00207 << "Request.Buffer" << endl;
00208 }
00209
00210 }
00211 else
00212 {
00213 escritos = write( tempfd, Request.Buffer, ObjSize % BlockSize );
00214
00215 if( escritos != ObjSize % BlockSize )
00216 {
00217 RioErr << "RioFile::Download erro ao escrever o valor de "
00218 << "Request.Buffer: escritos "<< escritos << " bytes "
00219 << "de um total de " << ObjSize % BlockSize << " bytes."
00220 << endl;
00221 }
00222 else if( escritos == -1 )
00223 {
00224 RioErr << "RioFile::Download erro " << errno << "("
00225 << strerror( errno ) << ") ao escrever o valor de "
00226 << "Request.Buffer" << endl;
00227 }
00228
00229 }
00230 pthread_mutex_unlock( &Mutex );
00231
00232 #ifdef RIO_DEBUG2
00233 RioErr << "[RioFile]: Download() - Released mutex..." << endl;
00234 #endif
00235
00236 block++;
00237 }
00238
00239 #ifdef RIO_DEBUG2
00240 RioErr << "[RioFile]: Download() - Finished download" << endl;
00241 #endif
00242
00243 close( tempfd );
00244
00245 pthread_mutex_destroy( &Mutex );
00246 pthread_cond_destroy( &Condition );
00247
00248 #ifdef RIO_DEBUG2
00249 RioErr << "[RioFile]: Saindo da Download" << endl;
00250 #endif
00251 }
00252
00253
00254
00255 int RioFile::Delete( void )
00256 {
00257 int rc = 1;
00258
00259 if( HasLocal )
00260 {
00261 #ifdef RIO_DEBUG2
00262 RioErr << "[RioFile]: Deletando arquivo " << LocalFilename << endl;
00263 #endif
00264
00265
00266
00267 rc = unlink( LocalFilename );
00268
00269 #ifdef RIO_DEBUG2
00270 if( rc == -1 )
00271 RioErr << "\tError removing temporary file object "
00272 << LocalFilename << endl;
00273 #endif
00274
00275 LocalFilename[ 0 ] = '\0';
00276 HasLocal = false;
00277 }
00278
00279 return rc;
00280 }
00281
00282 const char *RioFile::GetLocalFilename( void )
00283 {
00284 if( HasLocal )
00285 return LocalFilename;
00286 else
00287 return NULL;
00288 }
00289
00290 void RioFile::SetBufferStatus( int status )
00291 {
00292 #ifdef RIO_DEBUG2
00293 RioErr << "[RioFile]: SetBufferStatus() - Waiting on mutex..." << endl;
00294 #endif
00295
00296 pthread_mutex_lock( &Mutex );
00297
00298 BufferStatus = status;
00299 if( status == BUFFERFULL )
00300 {
00301 #ifdef RIO_DEBUG2
00302 RioErr << "[RioFile]: SetBufferStatus() - "
00303 << "Signalling condition..." << endl;
00304 #endif
00305
00306 pthread_cond_broadcast( &Condition );
00307 }
00308
00309 pthread_mutex_unlock( &Mutex );
00310
00311 #ifdef RIO_DEBUG2
00312 RioErr << "[RioFile]: SetBufferStatus() - Released mutex..." << endl;
00313 #endif
00314 }
00315
00316 void RioFile::CallBack( struct RioRequest *request )
00317 {
00318 RioFile *ptr;
00319
00320 #ifdef RIO_DEBUG2
00321 RioErr << "[RioFile]: CallBack() - Block arrived" << endl;
00322 #endif
00323
00324 ptr = (RioFile *)request->Who;
00325
00326 ptr->SetBufferStatus( BUFFERFULL );
00327 }