mirror of
				https://github.com/MariaDB/server.git
				synced 2025-10-31 02:46:29 +01:00 
			
		
		
		
	 dd5ce6b0c4
			
		
	
	
	dd5ce6b0c4
	
	
	
		
			
			log_file_t::read(), log_file_t::write(): Invoke pread() or pwrite() directly, so that we can give more accurate diagnostics in case of a failure, and so that we will avoid the overhead of setting up 5(!) stack frames and related objects. tpool::pwrite(): Add a missing const qualifier.
		
			
				
	
	
		
			164 lines
		
	
	
	
		
			3.9 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			164 lines
		
	
	
	
		
			3.9 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /* Copyright(C) 2019 MariaDB Corporation.
 | |
| 
 | |
| This program is free software; you can redistribute itand /or modify
 | |
| it under the terms of the GNU General Public License as published by
 | |
| the Free Software Foundation; version 2 of the License.
 | |
| 
 | |
| This program is distributed in the hope that it will be useful,
 | |
| but WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
 | |
| GNU General Public License for more details.
 | |
| 
 | |
| You should have received a copy of the GNU General Public License
 | |
| along with this program; if not, write to the Free Software
 | |
| Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111 - 1301 USA*/
 | |
| 
 | |
| #ifndef _WIN32
 | |
| #include <unistd.h> /* pread(), pwrite() */
 | |
| #endif
 | |
| #include "tpool.h"
 | |
| #include "tpool_structs.h"
 | |
| #include <stdlib.h>
 | |
| #include <string.h>
 | |
| 
 | |
| namespace tpool
 | |
| {
 | |
| #ifdef _WIN32
 | |
| 
 | |
| /*
 | |
|   In order to be able to execute synchronous IO even on file opened
 | |
|   with FILE_FLAG_OVERLAPPED, and to bypass  to completion port,
 | |
|   we use valid event handle for the hEvent member of the OVERLAPPED structure,
 | |
|   with its low-order bit set.
 | |
| 
 | |
|   See MSDN docs for GetQueuedCompletionStatus() for description of this trick.
 | |
| */
 | |
| static DWORD fls_sync_io= FLS_OUT_OF_INDEXES;
 | |
| HANDLE win_get_syncio_event()
 | |
| {
 | |
|   HANDLE h;
 | |
| 
 | |
|   h= (HANDLE) FlsGetValue(fls_sync_io);
 | |
|   if (h)
 | |
|   {
 | |
|     return h;
 | |
|   }
 | |
|   h= CreateEventA(NULL, FALSE, FALSE, NULL);
 | |
|   /* Set low-order bit to keeps I/O completion from being queued */
 | |
|   h= (HANDLE)((uintptr_t) h | 1);
 | |
|   FlsSetValue(fls_sync_io, h);
 | |
|   return h;
 | |
| }
 | |
| #include <WinIoCtl.h>
 | |
| static void __stdcall win_free_syncio_event(void *data)
 | |
| {
 | |
|   if (data)
 | |
|   {
 | |
|     CloseHandle((HANDLE) data);
 | |
|   }
 | |
| }
 | |
| 
 | |
| struct WinIoInit
 | |
| {
 | |
|   WinIoInit()
 | |
|   {
 | |
|     fls_sync_io= FlsAlloc(win_free_syncio_event);
 | |
|     if(fls_sync_io == FLS_OUT_OF_INDEXES)
 | |
| 	  abort();
 | |
|   }
 | |
|   ~WinIoInit() { FlsFree(fls_sync_io); }
 | |
| };
 | |
| 
 | |
| static WinIoInit win_io_init;
 | |
| 
 | |
| 
 | |
| SSIZE_T pread(const native_file_handle &h, void *buf, size_t count,
 | |
|               unsigned long long offset)
 | |
| {
 | |
|   OVERLAPPED ov{};
 | |
|   ULARGE_INTEGER uli;
 | |
|   uli.QuadPart= offset;
 | |
|   ov.Offset= uli.LowPart;
 | |
|   ov.OffsetHigh= uli.HighPart;
 | |
|   ov.hEvent= win_get_syncio_event();
 | |
|   if (count > 0xFFFFFFFF)
 | |
|     count= 0xFFFFFFFF;
 | |
| 
 | |
|   if (ReadFile(h, buf, (DWORD) count, 0, &ov) ||
 | |
|       (GetLastError() == ERROR_IO_PENDING))
 | |
|   {
 | |
|     DWORD n_bytes;
 | |
|     if (GetOverlappedResult(h, &ov, &n_bytes, TRUE))
 | |
|       return n_bytes;
 | |
|   }
 | |
| 
 | |
|   return -1;
 | |
| }
 | |
| 
 | |
| SSIZE_T pwrite(const native_file_handle &h, const void *buf, size_t count,
 | |
|                unsigned long long offset)
 | |
| {
 | |
|   OVERLAPPED ov{};
 | |
|   ULARGE_INTEGER uli;
 | |
|   uli.QuadPart= offset;
 | |
|   ov.Offset= uli.LowPart;
 | |
|   ov.OffsetHigh= uli.HighPart;
 | |
|   ov.hEvent= win_get_syncio_event();
 | |
|   if (count > 0xFFFFFFFF)
 | |
|     count= 0xFFFFFFFF;
 | |
|   if (WriteFile(h, buf, (DWORD) count, 0, &ov) ||
 | |
|       (GetLastError() == ERROR_IO_PENDING))
 | |
|   {
 | |
|     DWORD n_bytes;
 | |
|     if (GetOverlappedResult(h, &ov, &n_bytes, TRUE))
 | |
|       return n_bytes;
 | |
|   }
 | |
|   return -1;
 | |
| }
 | |
| #endif
 | |
| 
 | |
| /**
 | |
|   Simulated AIO.
 | |
| 
 | |
|   Executes IO synchronously in worker pool
 | |
|   and then calls the completion routine.
 | |
| */
 | |
| class simulated_aio : public aio
 | |
| {
 | |
|   thread_pool *m_pool;
 | |
| 
 | |
| public:
 | |
|   simulated_aio(thread_pool *tp)
 | |
|       : m_pool(tp)
 | |
|   {
 | |
|   }
 | |
| 
 | |
|   static void simulated_aio_callback(void *param)
 | |
|   {
 | |
|     aiocb *cb= (aiocb *) param;
 | |
|     synchronous(cb);
 | |
|     cb->m_internal_task.m_func= cb->m_callback;
 | |
|     thread_pool *pool= (thread_pool *)cb->m_internal;
 | |
|     pool->submit_task(&cb->m_internal_task);
 | |
|   }
 | |
| 
 | |
|   int submit_io(aiocb *aiocb) override
 | |
|   {
 | |
|     aiocb->m_internal_task.m_func = simulated_aio_callback;
 | |
|     aiocb->m_internal_task.m_arg = aiocb;
 | |
|     aiocb->m_internal_task.m_group = aiocb->m_group;
 | |
|     aiocb->m_internal = m_pool;
 | |
|     m_pool->submit_task(&aiocb->m_internal_task);
 | |
|     return 0;
 | |
|   }
 | |
| 
 | |
|   int bind(native_file_handle &fd) override { return 0; }
 | |
|   int unbind(const native_file_handle &fd) override { return 0; }
 | |
| };
 | |
| 
 | |
| aio *create_simulated_aio(thread_pool *tp)
 | |
| {
 | |
|   return new simulated_aio(tp);
 | |
| }
 | |
| 
 | |
| } // namespace tpool
 |