Пример #1
0
        void nfs_client_impl::local_write_callback(error_code err, size_t sz, dsn::ref_ptr<copy_request_ex> reqc)
        {
            //dassert(reqc->local_write_task == task::get_current_task(), "");
            --_concurrent_local_write_count;

            // clear all content to release memory quickly
            reqc->response.file_content = blob();

            continue_write();

            bool completed = false;
            if (err != ERR_OK)
            {
                completed = true;
            }
            else
            {
                zauto_lock l(reqc->file_ctx->user_req->user_req_lock);
                if (++reqc->file_ctx->finished_segments == (int)reqc->file_ctx->copy_requests.size())
                {
                    if (++reqc->file_ctx->user_req->finished_files == (int)reqc->file_ctx->user_req->file_context_map.size())
                    {
                        completed = true;
                    }
                }
            }

            if (completed)
            {   
                handle_completion(reqc->file_ctx->user_req, err);
            }
        }
Пример #2
0
        void nfs_client_impl::end_copy(
            ::dsn::error_code err,
            const copy_response& resp,
            void* context)
        {
            //dinfo("*** call RPC_NFS_COPY end, return (%d, %d) with %s", resp.offset, resp.size, err.to_string());

            dsn::ref_ptr<copy_request_ex> reqc;
            reqc = (copy_request_ex*)context;
            reqc->release_ref();

            continue_copy(1);
            
            if (err == ERR_OK)
            {
                err = resp.error;
            }

            if (err != ::dsn::ERR_OK)
            {
                handle_completion(reqc->file_ctx->user_req, err);
                return;
            }
            
            reqc->response = resp;
            reqc->response.error.end_tracking(); // always ERR_OK
            reqc->is_ready_for_write = true;

            auto& fc = reqc->file_ctx;

            // check write availability
            {
                zauto_lock l(fc->user_req->user_req_lock);
                if (fc->current_write_index != reqc->index - 1)
                    return;
            }

            // check readies for local writes
            {
                zauto_lock l(fc->user_req->user_req_lock);
                for (int i = reqc->index; i < (int)(fc->copy_requests.size()); i++)
                {
                    if (fc->copy_requests[i]->is_ready_for_write)
                    {
                        fc->current_write_index++;

                        {
                            zauto_lock l(_local_writes_lock);
                            _local_writes.push(fc->copy_requests[i]);
                        }
                    }
                    else
                        break;
                }
            }

            continue_write();
        }
Пример #3
0
static void ide_controller_write(struct ide_state *ide, offs_t offset, int size, UINT32 data)
{
	/* logit */
	if (offset != IDE_ADDR_DATA)
		LOG(("%08X:IDE write to %03X = %08X, size=%d\n", activecpu_get_previouspc(), offset, data, size));

	switch (offset)
	{
		/* unknown config register */
		case IDE_ADDR_CONFIG_UNK:
			ide->config_unknown = data;
			break;

		/* active config register */
		case IDE_ADDR_CONFIG_REGISTER:
			ide->config_register_num = data;
			break;

		/* data from active config register */
		case IDE_ADDR_CONFIG_DATA:
			if (ide->config_register_num < IDE_CONFIG_REGISTERS)
				ide->config_register[ide->config_register_num] = data;
			break;

		/* write data */
		case IDE_ADDR_DATA:
			if (ide->status & IDE_STATUS_BUFFER_READY)
			{
				/* store the correct amount of data */
				ide->buffer[ide->buffer_offset++] = data;
				if (size > 1)
					ide->buffer[ide->buffer_offset++] = data >> 8;
				if (size > 2)
				{
					ide->buffer[ide->buffer_offset++] = data >> 16;
					ide->buffer[ide->buffer_offset++] = data >> 24;
				}

				/* if we're at the end of the buffer, handle it */
				if (ide->buffer_offset >= IDE_DISK_SECTOR_SIZE)
				{
					if (ide->command != IDE_COMMAND_SECURITY_UNLOCK)
						continue_write(ide);
					else
					{
						if (ide->user_password_enable && memcmp(ide->buffer, ide->user_password, 2 + 32) == 0)
						{
							LOGPRINT(("IDE Unlocked user password\n"));
							ide->user_password_enable = 0;
						}
						if (ide->master_password_enable && memcmp(ide->buffer, ide->master_password, 2 + 32) == 0)
						{
							LOGPRINT(("IDE Unlocked master password\n"));
							ide->master_password_enable = 0;
						}
#if PRINTF_IDE_PASSWORD
						{
							int i;

							for (i = 0; i < 34; i += 2)
							{
								if (i % 8 == 2)
									printf("\n");

								printf("0x%02x, 0x%02x, ", ide->buffer[i], ide->buffer[i + 1]);
								//printf("0x%02x%02x, ", ide->buffer[i], ide->buffer[i + 1]);
							}
							printf("\n");
						}
#endif

						/* clear the busy adn error flags */
						ide->status &= ~IDE_STATUS_ERROR;
						ide->status &= ~IDE_STATUS_BUSY;
						ide->status &= ~IDE_STATUS_BUFFER_READY;

						if (ide->master_password_enable || ide->user_password_enable)
							security_error(ide);
						else
							ide->status |= IDE_STATUS_DRIVE_READY;
					}
				}
			}
Пример #4
0
void handle_command(struct ide_state *ide, UINT8 command)
{
	/* implicitly clear interrupts here */
	clear_interrupt(ide);

	ide->command = command;
	switch (command)
	{
		case IDE_COMMAND_READ_MULTIPLE:
		case IDE_COMMAND_READ_MULTIPLE_ONCE:
			LOGPRINT(("IDE Read multiple: C=%d H=%d S=%d LBA=%d count=%d\n",
				ide->cur_cylinder, ide->cur_head, ide->cur_sector, lba_address(ide), ide->sector_count));

			/* reset the buffer */
			ide->buffer_offset = 0;
			ide->sectors_until_int = 1;
			ide->dma_active = 0;

			/* start the read going */
			read_first_sector(ide);
			break;

		case IDE_COMMAND_READ_MULTIPLE_BLOCK:
			LOGPRINT(("IDE Read multiple block: C=%d H=%d S=%d LBA=%d count=%d\n",
				ide->cur_cylinder, ide->cur_head, ide->cur_sector, lba_address(ide), ide->sector_count));

			/* reset the buffer */
			ide->buffer_offset = 0;
			ide->sectors_until_int = 1;
			ide->dma_active = 0;

			/* start the read going */
			read_first_sector(ide);
			break;

		case IDE_COMMAND_READ_DMA:
			LOGPRINT(("IDE Read multiple DMA: C=%d H=%d S=%d LBA=%d count=%d\n",
				ide->cur_cylinder, ide->cur_head, ide->cur_sector, lba_address(ide), ide->sector_count));

			/* reset the buffer */
			ide->buffer_offset = 0;
			ide->sectors_until_int = ide->sector_count;
			ide->dma_active = 1;

			/* start the read going */
			if (ide->bus_master_command & 1)
				read_first_sector(ide);
			break;

		case IDE_COMMAND_WRITE_MULTIPLE:
			LOGPRINT(("IDE Write multiple: C=%d H=%d S=%d LBA=%d count=%d\n",
				ide->cur_cylinder, ide->cur_head, ide->cur_sector, lba_address(ide), ide->sector_count));

			/* reset the buffer */
			ide->buffer_offset = 0;
			ide->sectors_until_int = 1;
			ide->dma_active = 0;

			/* mark the buffer ready */
			ide->status |= IDE_STATUS_BUFFER_READY;
			break;

		case IDE_COMMAND_WRITE_MULTIPLE_BLOCK:
			LOGPRINT(("IDE Write multiple block: C=%d H=%d S=%d LBA=%d count=%d\n",
				ide->cur_cylinder, ide->cur_head, ide->cur_sector, lba_address(ide), ide->sector_count));

			/* reset the buffer */
			ide->buffer_offset = 0;
			ide->sectors_until_int = 1;
			ide->dma_active = 0;

			/* mark the buffer ready */
			ide->status |= IDE_STATUS_BUFFER_READY;
			break;

		case IDE_COMMAND_WRITE_DMA:
			LOGPRINT(("IDE Write multiple DMA: C=%d H=%d S=%d LBA=%d count=%d\n",
				ide->cur_cylinder, ide->cur_head, ide->cur_sector, lba_address(ide), ide->sector_count));

			/* reset the buffer */
			ide->buffer_offset = 0;
			ide->sectors_until_int = ide->sector_count;
			ide->dma_active = 1;

			/* start the read going */
			if (ide->bus_master_command & 1)
			{
				read_buffer_from_dma(ide);
				continue_write(ide);
			}
			break;

		case IDE_COMMAND_SECURITY_UNLOCK:
			LOGPRINT(("IDE Security Unlock\n"));

			/* reset the buffer */
			ide->buffer_offset = 0;
			ide->sectors_until_int = 0;
			ide->dma_active = 0;

			/* mark the buffer ready */
			ide->status |= IDE_STATUS_BUFFER_READY;
			signal_interrupt(ide);
			break;

		case IDE_COMMAND_GET_INFO:
			LOGPRINT(("IDE Read features\n"));

			/* reset the buffer */
			ide->buffer_offset = 0;
			ide->sector_count = 1;

			/* build the features page */
			memcpy(ide->buffer, ide->features, sizeof(ide->buffer));

			/* indicate everything is ready */
			ide->status |= IDE_STATUS_BUFFER_READY;
			ide->status |= IDE_STATUS_SEEK_COMPLETE;

			/* and clear the busy adn error flags */
			ide->status &= ~IDE_STATUS_ERROR;
			ide->status &= ~IDE_STATUS_BUSY;

			/* clear the error too */
			ide->error = IDE_ERROR_NONE;

			/* signal an interrupt */
			signal_delayed_interrupt(ide, MINIMUM_COMMAND_TIME, 1);
			break;

		case IDE_COMMAND_SET_CONFIG:
			LOGPRINT(("IDE Set configuration (%d heads, %d sectors)\n", ide->cur_head + 1, ide->sector_count));

			ide->num_sectors = ide->sector_count;
			ide->num_heads = ide->cur_head + 1;

			/* signal an interrupt */
			signal_interrupt(ide);
			break;

		case IDE_COMMAND_UNKNOWN_F9:
			/* only used by Killer Instinct AFAICT */
			LOGPRINT(("IDE unknown command (F9)\n"));

			/* signal an interrupt */
			signal_interrupt(ide);
			break;

		case IDE_COMMAND_SET_FEATURES:
			LOGPRINT(("IDE Set features (%02X %02X %02X %02X %02X)\n", ide->precomp_offset, ide->sector_count & 0xff, ide->cur_sector, ide->cur_cylinder & 0xff, ide->cur_cylinder >> 8));

			/* signal an interrupt */
			signal_delayed_interrupt(ide, MINIMUM_COMMAND_TIME, 0);
			break;
		
		case IDE_COMMAND_SET_BLOCK_COUNT:
			LOGPRINT(("IDE Set block count (%02X)\n", ide->sector_count));

			ide->block_count = ide->sector_count;
			// judge dredd wants 'drive ready' on this command
			ide->status |= IDE_STATUS_DRIVE_READY;

			/* signal an interrupt */
			signal_interrupt(ide);
			break;

		default:
			LOGPRINT(("IDE unknown command (%02X)\n", command));
#ifdef MAME_DEBUG
{
	extern int debug_key_pressed;
	debug_key_pressed = 1;
}
#endif
			break;
	}
}
Пример #5
0
static void write_sector_done(int which)
{
	struct ide_state *ide = &idestate[which];
	int lba = lba_address(ide), count = 0;

	/* now do the write */
	if (ide->disk)
		count = hard_disk_write(ide->disk, lba, 1, ide->buffer);

	/* by default, mark the buffer ready and the seek complete */
	ide->status |= IDE_STATUS_BUFFER_READY;
	ide->status |= IDE_STATUS_SEEK_COMPLETE;

	/* and clear the busy adn error flags */
	ide->status &= ~IDE_STATUS_ERROR;
	ide->status &= ~IDE_STATUS_BUSY;

	/* if we succeeded, advance to the next sector and set the nice bits */
	if (count == 1)
	{
		/* advance the pointers, unless this is the last sector */
		/* Gauntlet: Dark Legacy checks to make sure we stop on the last sector */
		if (ide->sector_count != 1)
			next_sector(ide);

		/* clear the error value */
		ide->error = IDE_ERROR_NONE;

		/* signal an interrupt */
		if (--ide->sectors_until_int == 0 || ide->sector_count == 1)
		{
			ide->sectors_until_int = ((ide->command == IDE_COMMAND_WRITE_MULTIPLE_BLOCK) ? ide->block_count : 1);
			signal_interrupt(ide);
		}

		/* signal an interrupt if there's more data needed */
		if (ide->sector_count > 0)
			ide->sector_count--;
		if (ide->sector_count == 0)
			ide->status &= ~IDE_STATUS_BUFFER_READY;

		/* keep going for DMA */
		if (ide->dma_active && ide->sector_count != 0)
		{
			read_buffer_from_dma(ide);
			continue_write(ide);
		}
		else
			ide->dma_active = 0;
	}

	/* if we got an error, we need to report it */
	else
	{
		/* set the error flag and the error */
		ide->status |= IDE_STATUS_ERROR;
		ide->error = IDE_ERROR_BAD_SECTOR;
		ide->bus_master_status |= IDE_BUSMASTER_STATUS_ERROR;
		ide->bus_master_status &= ~IDE_BUSMASTER_STATUS_ACTIVE;

		/* signal an interrupt */
		signal_interrupt(ide);
	}
}
Пример #6
0
void ide_controller_device::write_buffer_full()
{
	ide_device_interface *dev = slot[cur_drive]->dev();

	set_dmarq(0);
	if (command == IDE_COMMAND_SECURITY_UNLOCK)
	{
		if (user_password_enable && memcmp(buffer, user_password, 2 + 32) == 0)
		{
			LOGPRINT(("IDE Unlocked user password\n"));
			user_password_enable = 0;
		}
		if (master_password_enable && memcmp(buffer, master_password, 2 + 32) == 0)
		{
			LOGPRINT(("IDE Unlocked master password\n"));
			master_password_enable = 0;
		}
		if (PRINTF_IDE_PASSWORD)
		{
			int i;

			for (i = 0; i < 34; i += 2)
			{
				if (i % 8 == 2)
					mame_printf_debug("\n");

				mame_printf_debug("0x%02x, 0x%02x, ", buffer[i], buffer[i + 1]);
				//mame_printf_debug("0x%02x%02x, ", buffer[i], buffer[i + 1]);
			}
			mame_printf_debug("\n");
		}

		/* clear the busy and error flags */
		status &= ~IDE_STATUS_ERROR;
		status &= ~IDE_STATUS_BUSY;
		status &= ~IDE_STATUS_BUFFER_READY;

		if (master_password_enable || user_password_enable)
			security_error();
		else
			status |= IDE_STATUS_DRIVE_READY;
	}
	else if (command == IDE_COMMAND_TAITO_GNET_UNLOCK_2)
	{
		UINT8 key[5] = { 0 };
		int i, bad = 0;
		dev->read_key(key);

		for (i=0; !bad && i<512; i++)
			bad = ((i < 2 || i >= 7) && buffer[i]) || ((i >= 2 && i < 7) && buffer[i] != key[i-2]);

		status &= ~IDE_STATUS_BUSY;
		status &= ~IDE_STATUS_BUFFER_READY;
		if (bad)
			status |= IDE_STATUS_ERROR;
		else {
			status &= ~IDE_STATUS_ERROR;
			gnetreadlock= 0;
		}
	}
	else
	{
		continue_write();
	}
}
Пример #7
0
        void nfs_client_impl::handle_completion(user_request *req, error_code err)
        {
            {
                zauto_lock l(req->user_req_lock);
                if (req->is_finished)
                    return;

                req->is_finished = true;
            }

            for (auto& f : req->file_context_map)
            {
                
                for (auto& rc : f.second->copy_requests)
                {
                    ::dsn::task_ptr ctask, wtask;
                    {
                        zauto_lock l(rc->lock);
                        rc->is_valid = false;
                        ctask = rc->remote_copy_task;
                        wtask = rc->local_write_task;

                        rc->remote_copy_task = nullptr;
                        rc->local_write_task = nullptr;
                    }

                    if (err != ERR_OK)
                    {
                        if (ctask != nullptr)
                        {
                            if (ctask->cancel(true))
                            {
                                _concurrent_copy_request_count--;
                                rc->release_ref();
                            }
                        }

                        if (wtask != nullptr)
                        {
                            if (wtask->cancel(true))
                            {
                                _concurrent_local_write_count--;
                            }
                        }
                    }
                }
                                
                if (f.second->file)
                {
                    auto err2 = dsn_file_close(f.second->file);
                    dassert(err2 == ERR_OK, "dsn_file_close failed, err = %s", dsn_error_to_string(err2)); 

                    f.second->file = nullptr;

                    if (f.second->finished_segments != (int)f.second->copy_requests.size())
                    {
                        ::remove((f.second->user_req->file_size_req.dst_dir 
                            + f.second->file_name).c_str());
                    }

                    f.second->copy_requests.clear();
                }

                delete f.second;
            }

            req->file_context_map.clear();
            req->nfs_task->enqueue(err, 0);

            delete req;

            // clear out all canceled requests
            if (err != ERR_OK)
            {
                continue_copy(0);
                continue_write();
            }
        }
Пример #8
0
        void nfs_client_impl::continue_write()
        {
            // check write quota
            if (++_concurrent_local_write_count > _opts.max_concurrent_local_writes)
            {
                --_concurrent_local_write_count;
                return;
            }

            // get write
            dsn::ref_ptr<copy_request_ex> reqc;
            while (true)
            {
                {
                    zauto_lock l(_local_writes_lock);
                    if (!_local_writes.empty())
                    {
                        reqc = _local_writes.front();
                        _local_writes.pop();
                    }
                    else
                    {
                        reqc = nullptr;
                        break;
                    }   
                }

                {
                    zauto_lock l(reqc->lock);
                    if (reqc->is_valid)
                        break;
                }
            }

            if (nullptr == reqc)
            {
                --_concurrent_local_write_count;
                return;
            }   

            // real write
            std::string file_path = dsn::utils::filesystem::path_combine(reqc->copy_req.dst_dir, reqc->file_ctx->file_name);
            std::string path = dsn::utils::filesystem::remove_file_name(file_path.c_str());
            if (!dsn::utils::filesystem::create_directory(path))
            {
                dassert(false, "Fail to create directory %s.", path.c_str());
            }

            dsn_handle_t hfile = reqc->file_ctx->file.load();
            if (!hfile)
            {
                zauto_lock l(reqc->file_ctx->user_req->user_req_lock);
                hfile = reqc->file_ctx->file.load();
                if (!hfile)
                {
                    hfile = dsn_file_open(file_path.c_str(), O_RDWR | O_CREAT | O_BINARY, 0666);
                    reqc->file_ctx->file = hfile;
                }
            }

            if (!hfile)
            {
                derror("file open %s failed", file_path.c_str());
                error_code err = ERR_FILE_OPERATION_FAILED;
                handle_completion(reqc->file_ctx->user_req, err);
                --_concurrent_local_write_count;
                continue_write();
                return;
            }

            {
                zauto_lock l(reqc->lock);
                auto& reqc_save = *reqc.get();
                reqc_save.local_write_task = file::write(
                    hfile,
                    reqc_save.response.file_content.data(),
                    reqc_save.response.size,
                    reqc_save.response.offset,
                    LPC_NFS_WRITE,
                    this,
                    [this, reqc_cap = std::move(reqc)] (error_code err, int sz)
                    {
                        local_write_callback(err, sz, std::move(reqc_cap));
                    }
                );
            }
        }
Пример #9
0
        void nfs_client_impl::handle_completion(user_request *req, error_code err)
        {
            {
                zauto_lock l(req->user_req_lock);
                if (req->is_finished)
                    return;

                req->is_finished = true;
            }

            for (auto& f : req->file_context_map)
            {
                
                for (auto& rc : f.second->copy_requests)
                {
                    task_ptr ctask, wtask;
                    {
                        zauto_lock l(rc->lock);
                        rc->is_valid = false;
                        ctask = rc->remote_copy_task;
                        wtask = rc->local_write_task;

                        rc->remote_copy_task = nullptr;
                        rc->local_write_task = nullptr;
                    }

                    if (err != ERR_OK)
                    {
                        if (ctask != nullptr)
                        {
                            if (ctask->cancel(true))
                            {
                                _concurrent_copy_request_count--;
                                rc->release_ref();
                            }
                        }

                        if (wtask != nullptr)
                        {
                            if (wtask->cancel(true))
                            {
                                _concurrent_local_write_count--;
                            }
                        }
                    }
                }
                                
                if (f.second->file)
                {
                    file::close(f.second->file);
                    f.second->file = static_cast<handle_t>(0);

                    if (f.second->finished_segments != (int)f.second->copy_requests.size())
                    {
                        boost::filesystem::remove(f.second->user_req->file_size_req.dst_dir + f.second->file_name);
                    }
                }

                delete f.second;
            }

            req->file_context_map.clear();
            req->nfs_task->enqueue(err, 0, req->nfs_task->node());

            delete req;

            // clear out all canceled requests
            if (err != ERR_OK)
            {
                continue_copy(0);
                continue_write();
            }
        }
Пример #10
0
        void nfs_client_impl::continue_write()
        {
            // check write quota
            if (++_concurrent_local_write_count > _opts.max_concurrent_local_writes)
            {
                --_concurrent_local_write_count;
                return;
            }

            // get write
            boost::intrusive_ptr<copy_request_ex> reqc;
            while (true)
            {
                {
                    zauto_lock l(_local_writes_lock);
                    if (!_local_writes.empty())
                    {
                        reqc = _local_writes.front();
                        _local_writes.pop();
                    }
                    else
                    {
                        reqc = nullptr;
                        break;
                    }   
                }

                {
                    zauto_lock l(reqc->lock);
                    if (reqc->is_valid)
                        break;
                }
            }

            if (nullptr == reqc)
            {
                --_concurrent_local_write_count;
                return;
            }   

            // real write
            std::string file_path = reqc->copy_req.dst_dir + reqc->file_ctx->file_name;

            boost::filesystem::path path(file_path); // create directory recursively if necessary
            path = path.remove_filename();
            if (!boost::filesystem::exists(path))
            {
                boost::filesystem::create_directories(path);
            }

            handle_t hfile = reqc->file_ctx->file.load();
            if (!hfile)
            {
                zauto_lock l(reqc->file_ctx->user_req->user_req_lock);
                hfile = reqc->file_ctx->file.load();
                if (!hfile)
                {
                    hfile = file::open(file_path.c_str(), O_RDWR | O_CREAT | O_BINARY, 0666);
                    reqc->file_ctx->file = hfile;
                }
            }

            if (!hfile)
            {
                derror("file open %s failed", file_path.c_str());
                error_code err = ERR_FILE_OPERATION_FAILED;
                handle_completion(reqc->file_ctx->user_req, err);
                --_concurrent_local_write_count;
                continue_write();
                return;
            }

            {
                zauto_lock l(reqc->lock);

                reqc->local_write_task = file::write(
                    hfile,
                    reqc->response.file_content.data(),
                    reqc->response.size,
                    reqc->response.offset,
                    LPC_NFS_WRITE,
                    this,
                    std::bind(
                    &nfs_client_impl::local_write_callback,
                    this,
                    std::placeholders::_1,
                    std::placeholders::_2,
                    reqc
                    ),
                    0);
            }
        }