25 #ifndef SRC_XRDCL_XRDCLKERNELBUFFER_HH_
26 #define SRC_XRDCL_XRDCLKERNELBUFFER_HH_
78 pipes( std::move( kbuff.pipes ) )
94 capacity = kbuff.capacity;
96 pipes = std::move( kbuff.pipes );
105 if( capacity > 0 ) Free();
125 return ( ( uintptr_t ( ptr ) ) % PAGE_SZ ) == 0 ;
135 auto itr = pipes.begin();
136 for( ; itr != pipes.end() ; ++itr )
138 std::array<int, 2> &p = std::get<0>( *itr );
151 inline ssize_t Alloc(
size_t size )
158 std::array<int, 2> pipe_fd;
159 ret = pipe( pipe_fd.data() );
160 if( ret < 0 )
return ret;
162 if( size > MAX_PIPE_SIZE) size = MAX_PIPE_SIZE;
163 ret =
fcntl( pipe_fd[0], F_SETPIPE_SZ, size );
164 if( ret < 0 )
return ret;
167 pipes.emplace_back( pipe_fd, 0 );
183 #ifndef SPLICE_F_MOVE
184 inline ssize_t ReadFromFD(
int fd, uint32_t length, int64_t *offset )
189 inline ssize_t ReadFromFD(
int fd, uint32_t length, loff_t *offset )
191 if( capacity > 0 ) Free();
195 ssize_t ret = Alloc( length );
196 if( ret < 0 )
return ret;
197 if(
size_t( ret ) > length ) ret = length;
198 std::array<int, 2> &pipe_fd = std::get<0>( pipes.back() );
199 size_t &pipedata = std::get<1>( pipes.back() );
200 ret = splice( fd, offset, pipe_fd[1], NULL, ret, SPLICE_F_MOVE | SPLICE_F_MORE );
201 if( ret == 0 )
break;
202 if( ret < 0 )
return -1;
208 pipes_cursor = pipes.begin();
223 #ifndef SPLICE_F_MOVE
224 inline ssize_t WriteToFD(
int fd, int64_t *offset )
229 inline ssize_t WriteToFD(
int fd, loff_t *offset )
231 if( size == 0 )
return 0;
235 auto itr = pipes_cursor;
236 while( itr != pipes.end() )
238 std::array<int, 2> &pipe_fd = std::get<0>( *itr );
239 size_t &pipedata = std::get<1>( *itr );
241 int ret = splice( pipe_fd[0], NULL, fd, offset, size, SPLICE_F_MOVE | SPLICE_F_MORE );
242 if( ret == 0 )
break;
243 if( ret < 0 )
return -1;
250 if( pipedata > 0 )
continue;
278 inline ssize_t ToUser(
char *&buffer )
280 #ifndef SPLICE_F_MOVE
283 if( size == 0 )
return 0;
288 int ret = posix_memalign( &void_ptr, PAGE_SZ, size );
294 char *ptr =
reinterpret_cast<char*
>( void_ptr );
296 auto itr = pipes_cursor;
297 while( itr != pipes.end() )
300 size_t len = size > MAX_PIPE_SIZE ? MAX_PIPE_SIZE : size;
304 std::array<int, 2> &pipe_fd = std::get<0>( *itr );
305 size_t &pipedata = std::get<1>( *itr );
306 int ret = vmsplice( pipe_fd[0],
iov, 1, 0 );
324 if( pipedata > 0 )
continue;
332 buffer =
reinterpret_cast<char*
>( void_ptr );
355 inline ssize_t FromUser(
char *&buffer,
size_t length )
357 #ifndef SPLICE_F_MOVE
366 if( capacity > 0 ) Free();
371 ssize_t ret = Alloc( length );
372 if( ret < 0 )
return ret;
373 std::array<int, 2> &pipe_fd = std::get<0>( pipes.back() );
374 size_t &pipedata = std::get<1>( pipes.back() );
377 iov->iov_len = size_t( ret ) < length ? ret : length;
378 iov->iov_base = buff;
379 ret = vmsplice( pipe_fd[1],
iov, 1, SPLICE_F_GIFT );
381 if( ret < 0 )
return -1;
388 pipes_cursor = pipes.begin();
395 static const size_t PAGE_SZ = 4 * 1024;
396 static const size_t MAX_PIPE_SIZE = 1024 * 1024;
400 std::vector<std::tuple<std::array<int,2>,
size_t>> pipes;
401 std::vector<std::tuple<std::array<int,2>,
size_t>>::iterator pipes_cursor;
412 return buffer.ReadFromFD( fd, length, &offset );
423 return buffer.ReadFromFD( fd, length, NULL );
434 return buffer.WriteToFD( fd, &offset );
444 return buffer.WriteToFD( fd, NULL );
454 return kbuff.ToUser( ubuff );
464 return kbuff.FromUser( ubuff, length );
int fcntl(int fd, int cmd,...)
KernelBuffer()
Default constructor.
friend ssize_t Move(KernelBuffer &, char *&)
static bool IsPageAligned(const void *ptr)
friend ssize_t Read(int, KernelBuffer &, uint32_t, int64_t)
friend ssize_t Send(int, KernelBuffer &)
KernelBuffer(KernelBuffer &&kbuff)
KernelBuffer & operator=(const KernelBuffer &)=delete
Copy assignment operator - deleted.
KernelBuffer(const KernelBuffer &)=delete
Copy constructor - deleted.
~KernelBuffer()
Destructor.
friend ssize_t Write(int, KernelBuffer &, int64_t)
KernelBuffer & operator=(KernelBuffer &&kbuff)
Move assignment operator.
ssize_t Write(int fd, KernelBuffer &buffer, int64_t offset)
ssize_t Read(int fd, KernelBuffer &buffer, uint32_t length, int64_t offset)
ssize_t Move(KernelBuffer &kbuff, char *&ubuff)
ssize_t Send(int fd, KernelBuffer &buffer)