00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <fstream>
00025 #include <iostream>
00026 using namespace std;
00027
00028
00029 #include <stdio.h>
00030 #include <errno.h>
00031
00032
00033 #include <sys/types.h>
00034 #include <unistd.h>
00035
00036 #ifndef WINDOWS
00037
00038 #include <string.h>
00039 #include <sys/types.h>
00040 #include <sys/stat.h>
00041 #include <fcntl.h>
00042 #include <unistd.h>
00043 #include <linux/unistd.h>
00044 #endif
00045
00046 #include "RioInterface.h"
00047 #include "RioError.h"
00048 #include "FileObject.h"
00049 #include "RioTCPTypes.h"
00050
00051 const int MaxRequests = 10;
00052
00053
00054
00055
00056 LocalFileObject::LocalFileObject( char *filename )
00057 {
00058 strcpy( this->filename, filename );
00059 }
00060
00061
00062 bool LocalFileObject::Open( unsigned int mode, char *md5sum )
00063 {
00064 fd = open( filename, mode, DEFAULT_PERM );
00065
00066 return ( fd != -1 );
00067 }
00068
00069 int LocalFileObject::Close()
00070 {
00071 return close( fd );
00072 }
00073
00074 int LocalFileObject::Read(char *buf, int size)
00075 {
00076 return read( fd, buf, size );
00077 }
00078
00079 int LocalFileObject::Write(char *buf, int size, char *md5sum)
00080 {
00081 return write(fd, buf, size);
00082 }
00083
00084 RioObjectSize LocalFileObject::getSize()
00085 {
00086 #ifndef WINDOWS
00087 loff_t size;
00088 loff_t curPos;
00089
00090
00091
00092
00093
00094
00095 curPos = lseek64( fd, 0, SEEK_CUR );
00096 size = lseek64( fd, 0, SEEK_END );
00097 curPos = lseek64( fd, curPos, SEEK_SET );
00098 #else
00099 #ifdef __RIO_IRIX
00100 off64_t curPos;
00101 off64_t size;
00102 curPos = lseek64( fd, 0, SEEK_CUR );
00103 size=lseek64( fd, 0, SEEK_END );
00104 lseek( fd, curPos, SEEK_SET );
00105 #else
00106 offset_t curPos;
00107 offset_t size;
00108 curPos = llseek( fd, 0, SEEK_CUR );
00109 size=llseek( fd, 0, SEEK_END );
00110 llseek( fd, curPos, SEEK_SET );
00111 #endif
00112 #endif
00113 return size;
00114 }
00115
00116
00117
00118
00119
00120
00121
00122 bool LocalFileObject::getVideoRate( unsigned int *VideoRate )
00123 {
00124 *VideoRate = DEFAULTVIDEORATE;
00125 return true;
00126 }
00127
00128
00129
00130 bool LocalFileObject::setVideoRate( unsigned int VideoRate )
00131 {
00132 return true;
00133 }
00134
00135
00136 void ReadCallBack( RioRequest *Request )
00137 {
00138 RioFileObject *object = ( RioFileObject * )Request->User;
00139 object->Semaphore->V();
00140 }
00141
00142 void WriteCallBack( RioRequest *Request )
00143 {
00144 RioFileObject *object = ( RioFileObject * )Request->User;
00145 object->Semaphore->V();
00146 }
00147
00148
00149
00150
00151 RioFileObject::RioFileObject( CRioStream *stream, char *objectName )
00152 {
00153 this->stream = stream;
00154 curPos = 0;
00155 curBlock = 0;
00156 Semaphore = new CSemaphore( 0, MaxRequests );
00157
00158 strcpy( this->objectName, objectName );
00159 }
00160
00161 RioFileObject::~RioFileObject()
00162 {
00163 delete object;
00164 delete Semaphore;
00165 }
00166
00167 bool RioFileObject::Open( RioAccess access, char *md5sum )
00168 {
00169 RioResult hResult;
00170 CRioSession *session;
00171
00172 if( stream != NULL )
00173 {
00174 session = stream->GetRioSession();
00175 session->GetBlockSize( &blockSize );
00176 }
00177 else
00178 return false;
00179
00180 if( ( stream == NULL ) || ( stream->GetTrafficType() != RIO_TRAFFIC_NRT ) )
00181 {
00182 RioErr << " Stream nula ou inv�lida. Se inv�lida, � necess�ria "
00183 << "uma stream que n�o seja realtime." << endl;
00184
00185 return false;
00186 }
00187
00188 if( (access & RIO_WRITE_ACCESS) )
00189 {
00190 hResult = session->CreateObject( objectName,ObjectInfo::FILE_TYPE_DATA,
00191 NULL );
00192
00193 if( FAILED( hResult ) &&
00194 ( (hResult & 0xff) != (unsigned) ERROR_OBJECT_EXISTS )
00195 )
00196 {
00197 return false;
00198 }
00199 }
00200
00201 object = new CRioObject;
00202
00203 hResult = object->Open( objectName, access, stream );
00204 if( FAILED( hResult ) )
00205 {
00206 return false;
00207 }
00208
00209 if( (access & RIO_WRITE_ACCESS) )
00210 {
00211
00212
00213 hResult = object->SetSize( 0, md5sum );
00214 }
00215
00216 size = this->getSize();
00217
00218 return true;
00219 }
00220
00221 RioObjectSize RioFileObject::getSize()
00222 {
00223 RioObjectSize objSize;
00224 RioResult hResult;
00225
00226 hResult = object->GetSize (&objSize);
00227 if( FAILED( hResult ) )
00228 {
00229 RioErr << " Erro inesperado tentando pegar tamanho do objeto." << endl
00230 << endl;
00231 return (1);
00232 }
00233
00234 return objSize;
00235 }
00236
00237
00238
00239
00240 int RioFileObject::Close()
00241 {
00242 if( object )
00243 {
00244 object->Close();
00245 }
00246
00247 return 0;
00248 }
00249
00250 int RioFileObject::Read(char *buf, int size)
00251 {
00252 RioRequest Request;
00253 char* data = new char[blockSize];
00254 unsigned int done = 0;
00255 unsigned int bytes = 0;
00256 RioResult hResult;
00257
00258 unsigned int numberofretrys;
00259
00260 #ifdef RIO_DEBUG2
00261 struct timeval start, end;
00262 #endif
00263
00264 Request.Size = blockSize;
00265 Request.Buffer = data;
00266 Request.CallBackFunction = ReadCallBack;
00267 Request.User = (void *)this;
00268
00269
00270 numberofretrys = 0;
00271
00272 while( (done < (unsigned) size) && (curPos < this->size))
00273 {
00274
00275 #ifdef RIO_DEBUG2
00276 RioErr << "RioFileObject::Read tentativa " << numberofretrys + 1
00277 << " de ler o bloco " << curBlock << endl;
00278 #endif
00279
00280 bytes = size - done;
00281 if( bytes > blockSize )
00282 bytes = blockSize;
00283
00284 if( (bytes+curPos) > this->size )
00285 bytes = this->size-curPos;
00286
00287 Request.Block = curBlock;
00288 Request.Result = S_OK;
00289 Request.Status = RIO_REQUEST_FREE;
00290
00291 #ifdef RIO_DEBUG2
00292 gettimeofday( &start, NULL );
00293 #endif
00294
00295 hResult = object->StreamRead( &Request );
00296
00297 #ifdef RIO_DEBUG2
00298 gettimeofday( &end, NULL );
00299 RioErr << "RioFileObject::Read tempo para iniciar a leitura do bloco "
00300 << curBlock << " no servidor de armazenamento: "
00301 << (double) ( end.tv_sec - start.tv_sec ) +
00302 ( (double) ( end.tv_usec - start.tv_usec ) / 1000000.0 )
00303 << endl;
00304 #endif
00305
00306 if( FAILED( hResult ) )
00307 {
00308 RioErr << " N�o conseguiu ler objeto." << endl;
00309 return -1;
00310 }
00311
00312 Semaphore->P();
00313
00314 #ifdef RIO_DEBUG2
00315 memcpy( &start, &end, sizeof( struct timeval ) );
00316 gettimeofday( &end, NULL );
00317 RioErr << "RioFileObject::Read tempo para finalizar a leitura do bloco "
00318 << curBlock << " no servidor de armazenamento: "
00319 << (double) ( end.tv_sec - start.tv_sec ) +
00320 ( (double) ( end.tv_usec - start.tv_usec ) / 1000000.0 )
00321 << endl;
00322 #endif
00323
00324 if( Request.Result == S_OK )
00325 {
00326
00327
00328 memcpy( buf+done, data, bytes );
00329 curBlock++;
00330 done += bytes;
00331 curPos += bytes;
00332 numberofretrys = 0;
00333 }
00334 else if( ( Request.Result & 0xFF ) ==
00335 ERROR_SERVICE_TEMPORARY_UNAVAILABLE )
00336 {
00337
00338
00339
00340
00341
00342
00343 numberofretrys++;
00344 if( numberofretrys >= MAXNUMBEROFBLOCKRETRYS )
00345 {
00346 #ifdef RIO_DEBUG2
00347 RioErr << "RioFileObject::Read falhou em ler o bloco "
00348 << curBlock << ": numero de tentativas exedeu o maximo"
00349 << ". Abortando a leitura do bloco" << endl;
00350 #endif
00351 return -1;
00352 }
00353 }
00354 else
00355 {
00356 #ifdef RIO_DEBUG2
00357 RioErr << "RioFileObject::Read falhou em ler o bloco "<< curBlock
00358 << " com o erro 0x" << hex << ( unsigned int ) Request.Result
00359 << dec << " (" << GetErrorDescription( Request.Result )
00360 << ")" << endl;
00361 #endif
00362 return -1;
00363 }
00364
00365 }
00366
00367 delete data;
00368 return done;
00369 }
00370
00371 int RioFileObject::Write( char *buf, int size, char *md5sum )
00372 {
00373 RioRequest Request;
00374 RioResult hResult;
00375 unsigned int done = 0;
00376 unsigned int bytes = 0;
00377
00378 unsigned int numberofretrys;
00379
00380 #ifdef RIO_DEBUG2
00381 struct timeval start, end;
00382 #endif
00383
00384 Request.Size = blockSize;
00385 Request.CallBackFunction = WriteCallBack;
00386 Request.User = NULL;
00387 Request.User = (void *)this;
00388
00389
00390 numberofretrys = 0;
00391
00392 if( this->size < (curPos + size))
00393 {
00394 hResult = object->SetSize( curPos+size, md5sum );
00395 if( FAILED (hResult) )
00396 {
00397 RioErr << "N�o conseguiu alocar blocos para objeto.";
00398
00399 if( ( hResult & 0xff ) == (signed) ERROR_DISKFULL )
00400 RioErr << ": Disco(s) cheio(s)." << endl;
00401 else
00402 RioErr << ": erro = " << ( unsigned int ) ( hResult & 0xff )
00403 << endl;
00404
00405 return -1;
00406 }
00407
00408 this->size=curPos + size;
00409 }
00410
00411 while( done < (unsigned) size )
00412 {
00413
00414 #ifdef RIO_DEBUG2
00415 RioErr << "RioFileObject::Write tentativa " << numberofretrys + 1
00416 << " de escrever o bloco " << curBlock << endl;
00417 #endif
00418
00419 bytes = size - done;
00420 if( bytes > blockSize )
00421 bytes = blockSize;
00422
00423 Request.Buffer = buf + done;
00424 Request.Block = curBlock;
00425 Request.Result = S_OK;
00426 Request.Status = RIO_REQUEST_FREE;
00427
00428
00429 #ifdef RIO_DEBUG2
00430 gettimeofday( &start, NULL );
00431 #endif
00432
00433 hResult = object->StreamWrite( &Request );
00434
00435 #ifdef RIO_DEBUG2
00436 gettimeofday( &end, NULL );
00437 RioErr << "RioFileObject::Write tempo para iniciar a escrita do bloco "
00438 << curBlock << " no servidor de armazenamento: "
00439 << (double) ( end.tv_sec - start.tv_sec ) +
00440 ( (double) ( end.tv_usec - start.tv_usec ) / 1000000.0 )
00441 << endl;
00442 #endif
00443
00444 if( FAILED( hResult ) )
00445 {
00446 #ifdef RIO_DEBUG2
00447 RioErr << "RioFileObject::Write falhou em criar um NetBuf para "
00448 << "receber as identificacoes dos blocos fisicos para o "
00449 << "bloco logico " << curBlock << endl;
00450 #endif
00451 return -1;
00452 }
00453
00454 Semaphore->P();
00455
00456 #ifdef RIO_DEBUG2
00457 memcpy( &start, &end, sizeof( struct timeval ) );
00458 gettimeofday( &end, NULL );
00459 RioErr << "RioFileObject::Write tempo para finalizar a escrita do "
00460 << "bloco " << curBlock << " no servidor de armazenamento: "
00461 << (double) ( end.tv_sec - start.tv_sec ) +
00462 ( (double) ( end.tv_usec - start.tv_usec ) / 1000000.0 )
00463 << endl;
00464 #endif
00465
00466
00467 if( Request.Result == S_OK )
00468 {
00469
00470
00471 curBlock++;
00472 done += bytes;
00473 curPos += bytes;
00474 numberofretrys = 0;
00475 }
00476 else if( ( ( Request.Result & 0xFF ) ==
00477 ERROR_SERVICE_TEMPORARY_UNAVAILABLE ) ||
00478 ( ( Request.Result & 0xFF ) == ERROR_INVALID_DISK ) )
00479 {
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489 numberofretrys++;
00490 if( numberofretrys >= MAXNUMBEROFBLOCKRETRYS )
00491 {
00492 #ifdef RIO_DEBUG2
00493 RioErr << "RioFileObject::Write falhou em escrever o bloco "
00494 << curBlock << ": numero de tentativas exedeu o maximo"
00495 << ". Abortando a escrita do bloco" << endl;
00496 #endif
00497 return -1;
00498 }
00499
00500
00501 hResult = object->ReallocBlocks( curBlock );
00502 if( FAILED (hResult) )
00503 {
00504 #ifdef RIO_DEBUG2
00505 RioErr << "RioFileObject::Write falhou em realocar os blocos "
00506 << "fisicos do bloco logico " << curBlock << endl;
00507 #endif
00508 return -1;
00509 }
00510 #ifdef RIO_DEBUG2
00511 else
00512 RioErr << "RioFileObject::Write blocos fisicos do bloco logico "
00513 << curBlock << " realocados com sucesso" << endl;
00514 #endif
00515
00516 }
00517 else
00518 {
00519 #ifdef RIO_DEBUG2
00520 RioErr << "RioFileObject::Write falhou em escrever o bloco "
00521 << curBlock << " com o erro 0x" << hex
00522 << ( unsigned int ) Request.Result << dec
00523 << " (" << GetErrorDescription( Request.Result ) << ")"
00524 << endl;
00525 #endif
00526 return -1;
00527 }
00528
00529 }
00530
00531 return done;
00532 }
00533
00534
00535
00536
00537
00538
00539
00540
00541 bool RioFileObject::getVideoRate( unsigned int *VideoRate )
00542 {
00543 RioResult hResult;
00544
00545 hResult = object->GetVideoRate( VideoRate );
00546 if( FAILED( hResult ) )
00547 {
00548 RioErr << "RioFileObject::getVideoRate erro tentando pegar a taxa de "
00549 << "transmissao do objeto." << endl;
00550 return false;
00551 }
00552 return true;
00553 }
00554
00555
00556
00557
00558 bool RioFileObject::setVideoRate( unsigned int VideoRate )
00559 {
00560 RioResult hResult;
00561
00562 hResult = object->SetVideoRate( VideoRate );
00563 if( FAILED( hResult ) )
00564 {
00565 RioErr << "RioFileObject::setVideoRate erro tentando alterar a taxa de "
00566 << "transmissao do objeto." << endl;
00567 return false;
00568 }
00569 return true;
00570 }