bool GlusterBackend::put(const SyncEvent* _putEvent) { if(_putEvent == nullptr || _putEvent->fullPathBuffer.empty()) return false; FileNode* node = FileSystem::getInstance().findAndOpenNode(_putEvent->fullPathBuffer); if(node == nullptr){ LOG(ERROR)<<_putEvent->fullPathBuffer<<" Does not exist! So can't upload it."; return false; } uint64_t inodeNum = FileSystem::getInstance().assignINodeNum((intptr_t)node); //Double check if not already uploaded if(node->flushed()){ node->close(inodeNum); return true; } //CheckEvent validity if(!UploadQueue::getInstance().checkEventValidity(*_putEvent)) { //release file delete lock, so they can delete it node->close(inodeNum); return true;//going to be deletes so anyway say it's synced! } if(node->mustBeDeleted()){ node->close(inodeNum); return true; } //Create necessary directories //Traverse FileSystem Hierarchies Poco::StringTokenizer tokenizer(_putEvent->fullPathBuffer, FileSystem::delimiter,Poco::StringTokenizer::TOK_TRIM | Poco::StringTokenizer::TOK_IGNORE_EMPTY); //Nested directories if(tokenizer.count()>=2){ for(unsigned int i=0;i<tokenizer.count()-1;i++){ string path = FileSystem::delimiter; for(unsigned int j=0;j<=i;j++){ path += tokenizer[j]; path += FileSystem::delimiter; } if(!createDirectory(path.c_str())){ LOG(ERROR)<<"Failed to create parent directory("<<tokenizer[i]<<") for:"<<_putEvent->fullPathBuffer; node->close(inodeNum); return false; } } } //Create the file! (overwrite or create) glfs_fd_t *fd = glfs_creat((glfs_t*)fs, _putEvent->fullPathBuffer.c_str(), O_RDWR, 0644); //glfs_fd_t *fd = glfs_open(,O_RDWR| O_CREAT | O_TRUNC); if(!fd){ LOG(ERROR)<<"Error in creating file:"<<_putEvent->fullPathBuffer<<" in GlusterFS. errno:"<<errno; return false; } //Ready to write (write each time a blocksize) uint64_t buffSize = 1024ll*1024ll*10ll; char *buff = new char[buffSize];//10MB buffer size_t offset = 0; long read = 0; //FileNode *node = _putEvent->node; do { //CheckEvent validity if(!UploadQueue::getInstance().checkEventValidity(*_putEvent)){ glfs_close(fd); delete []buff; buff = nullptr; node->close(inodeNum); return true; } if(node->mustBeDeleted()){//Check Delete glfs_close(fd); delete []buff; buff = nullptr; node->close(inodeNum); return true; } //get lock delete so file won't be deleted read = node->read(buff,offset,buffSize); offset += read; int64_t written = glfs_write(fd,buff,read,0); if(written!=read){ LOG(ERROR)<<"Error while writing to:"<<_putEvent->fullPathBuffer<< ". Asked to write:"<<read<<" but wrote:"<<written; glfs_close(fd); return false; } } while(read > 0); delete []buff; buff = nullptr; if(node->mustBeDeleted()){//Check Delete glfs_close(fd); node->close(inodeNum); return true; } //Now sync if(glfs_close(fd)!=0){ LOG(ERROR)<<"Error in closing:"<<_putEvent->fullPathBuffer<<" errorNo:"<<errno; node->close(inodeNum); return false; } node->close(inodeNum); return true; }
bool GlusterBackend::get(const SyncEvent* _getEvent) { if(_getEvent == nullptr || _getEvent->fullPathBuffer.empty()) return false; //Try to find file /** * RETURN VALUES * NULL : Failure. @errno will be set with the type of failure. * Others : Pointer to the opened glfs_fd_t. */ glfs_fd_t *fd = glfs_open((glfs_t*)fs, _getEvent->fullPathBuffer.c_str(), O_RDONLY); if(!fd){ LOG(ERROR)<<"Error while openeing a handle to:"<<_getEvent->fullPathBuffer; return false; } FileNode* fileNode = FileSystem::getInstance().findAndOpenNode(_getEvent->fullPathBuffer); //If File exist then we won't download it! if(fileNode!=nullptr){ LOG(DEBUG)<<"File "<<fileNode->getFullPath()<<" already exist! no need to download."; //Close it! so it can be removed if needed uint64_t inodeNum = FileSystem::getInstance().assignINodeNum((intptr_t)fileNode); fileNode->close(inodeNum); glfs_close(fd); return false; } //Now create a file in FS //handle directories //FileSystem::getInstance().createHierarchy(_getEvent->fullPathBuffer,false); //FileNode *newFile = FileSystem::getInstance().mkFile(_getEvent->fullPathBuffer,false,true);//open string name = FileSystem::getInstance().getFileNameFromPath(_getEvent->fullPathBuffer); FileNode* newFile = new FileNode(name,_getEvent->fullPathBuffer, false,false); if(newFile == nullptr){ LOG(ERROR)<<"Failed to create a newNode:"<<_getEvent->fullPathBuffer; glfs_close(fd); return false; } //and write the content uint64_t bufSize = 64ll*1024ll*1024ll; char *buff = new char[bufSize];//64MB buffer size_t offset = 0; int64_t read = 0; do { //No need to download it anymore. if(newFile->mustBeDeleted()){ delete newFile; glfs_close(fd); return true; } read = glfs_pread(fd,buff,bufSize,offset,0); if(read < 0){ LOG(ERROR)<<"Error while reading: "<<_getEvent->fullPathBuffer; glfs_close(fd); return false; } if(read>0){ FileNode* afterMove = nullptr; long retCode = newFile->writeHandler(buff,offset,read,afterMove,true); while(retCode == -1)//-1 means moving retCode = newFile->writeHandler(buff,offset,read,afterMove,true); if(afterMove){ newFile = afterMove; FileSystem::getInstance().replaceAllInodesByNewNode((intptr_t)newFile,(intptr_t)afterMove); } //Check space availability if(retCode < 0) { LOG(ERROR)<<"Error in writing file:"<<newFile->getFullPath()<<", probably no diskspace, Code:"<<retCode; delete newFile; glfs_close(fd); delete []buff; return false; } } offset += read; }while(read); newFile->setNeedSync(false);//We have just created this file so it's upload flag false glfs_close(fd); delete []buff; //Add it to File system if(FileSystem::getInstance().createHierarchy(_getEvent->fullPathBuffer,false)==nullptr){ LOG(ERROR)<<"Error in creating hierarchy for newly downloaded file:"<<newFile->getFullPath(); delete newFile; return false; } if(!FileSystem::getInstance().addFile(newFile)){ LOG(ERROR)<<"Error in adding newly downloaded file:"<<newFile->getFullPath(); delete newFile; return false; } //Gone well return true; }