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); } }
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(); }
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; } } }
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; } }
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); } }
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(); } }
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(); } }
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)); } ); } }
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(); } }
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); } }