/** * Parse a data placement policy. */ int _xml_parse_policy(xmlTextReaderPtr reader, struct ltfs_index *idx) { declare_parser_vars("dataplacementpolicy"); declare_tracking_arrays(1, 0); /* get rid of unused variable warning */ (void) value; /* parse the contents of the policy tag */ while (true) { get_next_tag(); if (! strcmp(name, "indexpartitioncriteria")) { check_required_tag(0); assert_not_empty(); if (_xml_parse_ip_criteria(reader, idx) < 0) return -1; } else ignore_unrecognized_tag(); } check_required_tags(); return 0; }
/** * Parse a partition map from an XML file, storing it in the given label structure. */ int _xml_parse_partition_map(xmlTextReaderPtr reader, struct ltfs_label *label) { declare_parser_vars("partitions"); declare_tracking_arrays(2, 0); while (true) { get_next_tag(); if (! strcmp(name, "index")) { check_required_tag(0); get_tag_text(); if (_xml_parse_partition(value) < 0) return -1; label->partid_ip = value[0]; check_tag_end("index"); } else if (! strcmp(name, "data")) { check_required_tag(1); get_tag_text(); if (_xml_parse_partition(value) < 0) return -1; label->partid_dp = value[0]; check_tag_end("data"); } else ignore_unrecognized_tag(); } check_required_tags(); return 0; }
static int _xml_parse_symlink_target(xmlTextReaderPtr reader, int idx_version, struct dentry *d) { declare_parser_vars_symlinknode("symlink"); declare_tracking_arrays(1, 0); while (true) { get_next_tag(); if (! strcmp(name, "target")) { get_tag_text(); d->isslink = true; d->target = strdup(value); } else ignore_unrecognized_tag(); } return 0; }
/** * Parse an extent list from a file and populate provided dentry with the extents read during * the scanning. * * @param filename File name from where to read the extent list from. * @param d Dentry where the extents are to be appended to. * @return 0 on success or a negative value on error. */ static int xml_extentlist_from_file(const char *filename, struct dentry *d) { declare_extent_parser_vars("extentinfo"); xmlTextReaderPtr reader; xmlDocPtr doc; int ret = 0; CHECK_ARG_NULL(filename, -LTFS_NULL_ARG); CHECK_ARG_NULL(d, -LTFS_NULL_ARG); reader = xmlReaderForFile(filename, NULL, XML_PARSE_NOERROR | XML_PARSE_NOWARNING); if (! reader) { ltfsmsg(LTFS_ERR, "17011E", filename); return -1; } /* Workaround for old libxml2 version on OS X 10.5: the method used to preserve * unknown tags modifies the behavior of xmlFreeTextReader so that an additional * xmlDocFree call is required to free all memory. */ doc = xmlTextReaderCurrentDoc(reader); while (true) { /* BEAM: loop doesn't iterate - Because get_next_tag() macro uses "break", at most once loop is needed here. */ get_next_tag(); if (! strcmp(name, "extentinfo")) { ret = _xml_parse_extents(reader, IDX_VERSION_SPARSE, d); if (ret < 0) { /* XML parser: failed to read extent list from file (%d) */ ltfsmsg(LTFS_ERR, "17084E", ret); } } break; } if (doc) xmlFreeDoc(doc); xmlFreeTextReader(reader); return ret; }
/** * Parse a partition location from a label. */ int _xml_parse_label_location(xmlTextReaderPtr reader, struct ltfs_label *label) { declare_parser_vars("location"); declare_tracking_arrays(1, 0); while (true) { get_next_tag(); if (! strcmp(name, "partition")) { check_required_tag(0); get_tag_text(); if (_xml_parse_partition(value) < 0) return -1; label->this_partition = value[0]; check_tag_end("partition"); } else ignore_unrecognized_tag(); } check_required_tags(); return 0; }
/** * Parse a directory tree from the given XML source into the given index data structure. * @param reader the XML source * @param parent Directory where the new subdirectory should be created, or NULL to populate the * root dentry. * @param idx LTFS index data * @param vol LTFS volume to which the index belongs. May be NULL. * @return 0 on success or a negative value on error */ int _xml_parse_dirtree(xmlTextReaderPtr reader, struct dentry *parent, struct ltfs_index *idx, struct ltfs_volume *vol, struct name_list *dirname) { int ret; unsigned long long value_int; struct dentry *dir; declare_parser_vars("directory"); declare_tracking_arrays(9, 1); if (! parent && idx->root) { dir = idx->root; dir->vol = vol; } else { dir = fs_allocate_dentry(parent, NULL, NULL, true, false, false, idx); if (! dir) { ltfsmsg(LTFS_ERR, "10001E", __FUNCTION__); return -LTFS_NO_MEMORY; } if (! parent) { idx->root = dir; dir->vol = vol; ++dir->link_count; } } while (true) { get_next_tag(); if (!strcmp(name, "name")) { check_required_tag(0); if (parent) { get_tag_text(); if (xml_parse_filename(&dir->name, value) < 0) return -1; dirname->name = dir->name; dirname->d = dir; check_tag_end("name"); } else { /* this is the root directory, so set the volume name */ check_empty(); if (empty > 0) { value = NULL; } else { if (xml_scan_text(reader, &value) < 0) return -1; } if (value && strlen(value) > 0) { if (xml_parse_filename(&idx->volume_name, value) < 0) return -1; /* if the value is the empty string, then xml_scan_text consumed the "name" * element end */ check_tag_end("name"); } else idx->volume_name = NULL; } } else if (!strcmp(name, "readonly")) { check_required_tag(1); get_tag_text(); if (xml_parse_bool(&dir->readonly, value) < 0) return -1; check_tag_end("readonly"); } else if (!strcmp(name, "modifytime")) { check_required_tag(2); get_tag_text(); ret = xml_parse_time(true, value, &dir->modify_time); if (ret < 0) return -1; else if (ret == LTFS_TIME_OUT_OF_RANGE) ltfsmsg(LTFS_WARN, "17220W", "updatetime", dir->name, dir->uid, value); check_tag_end("modifytime"); } else if (!strcmp(name, "creationtime")) { check_required_tag(3); get_tag_text(); ret = xml_parse_time(true, value, &dir->creation_time); if (ret < 0) return -1; else if (ret == LTFS_TIME_OUT_OF_RANGE) ltfsmsg(LTFS_WARN, "17220W", "creationtime", dir->name, dir->uid, value); check_tag_end("creationtime"); } else if (!strcmp(name, "accesstime")) { check_required_tag(4); get_tag_text(); ret = xml_parse_time(true, value, &dir->access_time); if (ret < 0) return -1; else if (ret == LTFS_TIME_OUT_OF_RANGE) ltfsmsg(LTFS_WARN, "17220W", "accesstime", dir->name, dir->uid, value); check_tag_end("accesstime"); } else if (!strcmp(name, "changetime")) { check_required_tag(5); get_tag_text(); ret = xml_parse_time(true, value, &dir->change_time); if (ret < 0) return -1; else if (ret == LTFS_TIME_OUT_OF_RANGE) ltfsmsg(LTFS_WARN, "17220W", "changetime", dir->name, dir->uid, value); check_tag_end("changetime"); } else if (! strcmp(name, "contents")) { check_required_tag(6); check_empty(); if (empty == 0 && (ret = _xml_parse_dir_contents(reader, dir, idx)) < 0) { if (ret == -LTFS_NO_MEMORY) return ret; else return -1; } } else if (!strcmp(name, "extendedattributes")) { check_optional_tag(0); check_empty(); if (empty == 0 && _xml_parse_xattrs(reader, dir) < 0) return -1; } else if (idx->version >= IDX_VERSION_UID && ! strcmp(name, UID_TAGNAME)) { check_required_tag(7); get_tag_text(); if (xml_parse_ull(&value_int, value) < 0) return -1; dir->uid = value_int; if (dir->uid > idx->uid_number) idx->uid_number = dir->uid; if (parent) { dirname->uid = dir->uid; } check_tag_end(UID_TAGNAME); } else if (! strcmp(name, UID_TAGNAME)) { ignore_unrecognized_tag(); } else if (idx->version >= IDX_VERSION_BACKUPTIME && ! strcmp(name, BACKUPTIME_TAGNAME)) { check_required_tag(8); get_tag_text(); ret = xml_parse_time(true, value, &dir->backup_time); if (ret < 0) return -1; else if (ret == LTFS_TIME_OUT_OF_RANGE) ltfsmsg(LTFS_WARN, "17220W", "backuptime", dir->name, dir->uid, value); check_tag_end(BACKUPTIME_TAGNAME); } else if (! strcmp(name, BACKUPTIME_TAGNAME)) { ignore_unrecognized_tag(); } else preserve_unrecognized_tag(dir); } /* For old index versions, allocate a UID */ if (idx->version < IDX_VERSION_UID) { check_required_tag(7); if (parent) { dir->uid = fs_allocate_uid(idx); if (dir->uid > idx->uid_number) idx->uid_number = dir->uid; dirname->uid = dir->uid; } /* root directory already got assigned UID 1 by fs_allocate_dentry */ } /* For old index versions, set backup time equal to creation time */ if (idx->version < IDX_VERSION_BACKUPTIME) { check_required_tag(8); dir->backup_time = dir->creation_time; } check_required_tags(); /* Validate UID: root directory must have uid==1, other dentries must have nonzero UID */ /* TODO: would be nice to verify that there are no UID conflicts */ if (parent && dir->uid == 1) { ltfsmsg(LTFS_ERR, "17101E"); return -1; } else if (! parent && dir->uid != 1) { ltfsmsg(LTFS_ERR, "17100E"); return -1; } else if (dir->uid == 0) { ltfsmsg(LTFS_ERR, "17106E"); return -1; } return 0; }
/** * Parse index partition criteria. */ int _xml_parse_ip_criteria(xmlTextReaderPtr reader, struct ltfs_index *idx) { int ret; unsigned long long value_int; char *glob_norm; int num_patterns = 0; declare_parser_vars("indexpartitioncriteria"); declare_tracking_arrays(1, 0); /* clear the glob pattern list first */ index_criteria_free(&idx->original_criteria); index_criteria_free(&idx->index_criteria); /* We have a policy. */ idx->original_criteria.have_criteria = true; while (true) { get_next_tag(); if (! strcmp(name, "size")) { check_required_tag(0); get_tag_text(); if (xml_parse_ull(&value_int, value) < 0) { ltfsmsg(LTFS_ERR, "17024E", value); return -1; } idx->original_criteria.max_filesize_criteria = value_int; check_tag_end("size"); } else if (! strcmp(name, "name")) { get_tag_text(); if (pathname_validate_file(value) < 0) { ltfsmsg(LTFS_ERR, "17098E", value); return -1; } ++num_patterns; /* quite inefficient, but the number of patterns should be small. */ idx->original_criteria.glob_patterns = realloc(idx->original_criteria.glob_patterns, (num_patterns + 1) * sizeof(char *)); if (! idx->original_criteria.glob_patterns) { ltfsmsg(LTFS_ERR, "10001E", __FUNCTION__); return -1; } idx->original_criteria.glob_patterns[num_patterns] = NULL; ret = pathname_normalize(value, &glob_norm); if (ret < 0) { ltfsmsg(LTFS_ERR, "17025E", ret); return ret; } idx->original_criteria.glob_patterns[num_patterns - 1] = glob_norm; check_tag_end("name"); } else ignore_unrecognized_tag(); } /* Make an active copy of these index criteria. The caller can override idx->index_criteria * later without affecting the criteria stored in future indexes (idx->original_criteria). */ if (index_criteria_dup_rules(&idx->index_criteria, &idx->original_criteria) < 0) { /* Could not duplicate index criteria rules */ ltfsmsg(LTFS_ERR, "11301E"); return -1; } check_required_tags(); return 0; }
/** * Parse an index file from the given source and populate the priv->root virtual dentry tree. * with the nodes found during the scanning. * @param reader Source of XML data * @param idx LTFS index * @param vol LTFS volume to which the index belongs. May be NULL. * @return 0 on success or a negative value on error. */ int _xml_parse_schema(xmlTextReaderPtr reader, struct ltfs_index *idx, struct ltfs_volume *vol) { int ret; unsigned long long value_int; declare_parser_vars("ltfsindex"); declare_tracking_arrays(8, 3); /* start the parser: find top-level "index" tag, check version and encoding */ ret = _xml_parser_init(reader, parent_tag, &idx->version, LTFS_INDEX_VERSION_MIN, LTFS_INDEX_VERSION_MAX); if (ret < 0) return ret; if (idx->version < LTFS_INDEX_VERSION) ltfsmsg(LTFS_WARN, "17095W", LTFS_INDEX_VERSION_STR, LTFS_FORMAT_MAJOR(idx->version), LTFS_FORMAT_MINOR(idx->version), LTFS_FORMAT_REVISION(idx->version)); else if (idx->version / 100 > LTFS_INDEX_VERSION / 100) ltfsmsg(LTFS_WARN, "17096W", LTFS_INDEX_VERSION_STR, LTFS_FORMAT_MAJOR(idx->version), LTFS_FORMAT_MINOR(idx->version), LTFS_FORMAT_REVISION(idx->version)); else if (idx->version > LTFS_INDEX_VERSION) ltfsmsg(LTFS_WARN, "17234W", LTFS_INDEX_VERSION_STR, LTFS_FORMAT_MAJOR(idx->version), LTFS_FORMAT_MINOR(idx->version), LTFS_FORMAT_REVISION(idx->version)); if (idx->commit_message) { free(idx->commit_message); idx->commit_message = NULL; } /* parse index file contents */ while (true) { get_next_tag(); if (! strcmp(name, "creator")) { check_required_tag(0); get_tag_text(); if (idx->creator) free(idx->creator); idx->creator = strdup(value); if (! idx->creator) { ltfsmsg(LTFS_ERR, "10001E", name); return -1; } check_tag_end("creator"); } else if (! strcmp(name, "volumeuuid")) { check_required_tag(1); get_tag_text(); if (xml_parse_uuid(idx->vol_uuid, value) < 0) return -1; check_tag_end("volumeuuid"); } else if (! strcmp(name, "generationnumber")) { check_required_tag(2); get_tag_text(); if (xml_parse_ull(&value_int, value) < 0) { ltfsmsg(LTFS_ERR, "17023E", value); return -1; } idx->generation = value_int; check_tag_end("generationnumber"); } else if (! strcmp(name, "updatetime")) { check_required_tag(3); get_tag_text(); ret = xml_parse_time(true, value, &idx->mod_time); if (ret < 0) return -1; else if (ret == LTFS_TIME_OUT_OF_RANGE) ltfsmsg(LTFS_WARN, "17219W", "updatetime", value); check_tag_end("updatetime"); } else if (! strcmp(name, "location")) { check_required_tag(4); assert_not_empty(); if (_xml_scan_tapepos(reader, "location", &idx->selfptr) < 0) return -1; } else if (! strcmp(name, "allowpolicyupdate")) { check_required_tag(5); get_tag_text(); if (xml_parse_bool(&idx->criteria_allow_update, value) < 0) return -1; check_tag_end("allowpolicyupdate"); } else if (! strcmp(name, "directory")) { check_required_tag(6); assert_not_empty(); if ((ret = _xml_parse_dirtree(reader, NULL, idx, vol, NULL)) < 0) { if (ret == -LTFS_NO_MEMORY) return -LTFS_NO_MEMORY; else return -1; } } else if (! strcmp(name, "previousgenerationlocation")) { check_optional_tag(0); assert_not_empty(); if (_xml_scan_tapepos(reader, "previousgenerationlocation", &idx->backptr) < 0) return -1; } else if (! strcmp(name, "dataplacementpolicy")) { check_optional_tag(1); assert_not_empty(); if (_xml_parse_policy(reader, idx) < 0) return -1; } else if (! strcmp(name, "comment")) { check_optional_tag(2); get_tag_text(); if (strlen(value) > INDEX_MAX_COMMENT_LEN) { ltfsmsg(LTFS_ERR, "17094E"); return -1; } idx->commit_message = strdup(value); if (! idx->commit_message) { ltfsmsg(LTFS_ERR, "10001E", "_xml_parse_schema: index comment"); return -1; } check_tag_end("comment"); } else if (idx->version >= IDX_VERSION_UID && ! strcmp(name, NEXTUID_TAGNAME)) { check_required_tag(7); get_tag_text(); if (xml_parse_ull(&value_int, value) < 0) return -1; if (value_int > idx->uid_number) idx->uid_number = value_int; check_tag_end(NEXTUID_TAGNAME); } else if (! strcmp(name, NEXTUID_TAGNAME)) { ignore_unrecognized_tag(); } else preserve_unrecognized_tag(idx); } /* For older index versions, assume we handle UIDs correctly. * The idx->uid_number field is automatically initialized to 1, so it will be set correctly * once all files and directories are parsed. */ if (idx->version < IDX_VERSION_UID) check_required_tag(7); check_required_tags(); if ( idx->symerr_count != 0 ) { return -LTFS_SYMLINK_CONFLICT; } return 0; }
/** * Parse an XML label, populating the given label data structure. */ int _xml_parse_label(xmlTextReaderPtr reader, struct ltfs_label *label) { int ret; unsigned long long value_int; declare_parser_vars("ltfslabel"); declare_tracking_arrays(7, 0); /* start the parser: find top-level "label" tag, check version and encoding */ if (_xml_parser_init(reader, parent_tag, &label->version, LTFS_LABEL_VERSION_MIN, LTFS_LABEL_VERSION_MAX) < 0) return -1; /* parse label contents */ while (true) { get_next_tag(); if (! strcmp(name, "creator")) { check_required_tag(0); get_tag_text(); if (label->creator) { free(label->creator); label->creator = NULL; } label->creator = strdup(value); if (! label->creator) { ltfsmsg(LTFS_ERR, "10001E", name); return -1; } check_tag_end("creator"); } else if (! strcmp(name, "formattime")) { check_required_tag(1); get_tag_text(); ret = xml_parse_time(true, value, &label->format_time); if (ret < 0) return -1; else if (ret == LTFS_TIME_OUT_OF_RANGE) ltfsmsg(LTFS_WARN, "17218W", "formattime", value); check_tag_end("formattime"); } else if (! strcmp(name, "volumeuuid")) { check_required_tag(2); get_tag_text(); if (xml_parse_uuid(label->vol_uuid, value) < 0) return -1; check_tag_end("volumeuuid"); } else if (! strcmp(name, "location")) { check_required_tag(3); assert_not_empty(); if (_xml_parse_label_location(reader, label) < 0) return -1; } else if (! strcmp(name, "partitions")) { check_required_tag(4); assert_not_empty(); if (_xml_parse_partition_map(reader, label) < 0) return -1; } else if (! strcmp(name, "blocksize")) { check_required_tag(5); get_tag_text(); if (xml_parse_ull(&value_int, value) < 0 || value_int == 0) { ltfsmsg(LTFS_ERR, "17022E", value); return -1; } label->blocksize = value_int; check_tag_end("blocksize"); } else if (! strcmp(name, "compression")) { check_required_tag(6); get_tag_text(); if (xml_parse_bool(&label->enable_compression, value) < 0) return -1; check_tag_end("compression"); } else ignore_unrecognized_tag(); } check_required_tags(); return 0; }
int _xml_parse_dir_contents(xmlTextReaderPtr reader, struct dentry *dir, struct ltfs_index *idx) { int ret = 0; struct name_list *list = NULL, *entry_name = NULL; CHECK_ARG_NULL(dir, -LTFS_NULL_ARG); declare_parser_vars("contents"); declare_tracking_arrays(0, 0); /* get rid of unused variable warning */ (void) value; errno = 0; while (true) { get_next_tag(); if (! strcmp(name, "file")) { assert_not_empty(); entry_name = (struct name_list *)malloc(sizeof(struct name_list)); if (!entry_name) { ltfsmsg(LTFS_ERR, "10001E", "_xml_parse_dir_contents: file"); return -LTFS_NO_MEMORY; } if ((ret = _xml_parse_file(reader, idx, dir, entry_name)) < 0) { free(entry_name); if (ret == -LTFS_NO_MEMORY) return -LTFS_NO_MEMORY; else return -1; } } else if (! strcmp(name, "directory")) { assert_not_empty(); entry_name = (struct name_list *)malloc(sizeof(struct name_list)); if (!entry_name) { ltfsmsg(LTFS_ERR, "10001E", "_xml_parse_dir_contents: dir"); return -LTFS_NO_MEMORY; } if ((ret =_xml_parse_dirtree(reader, dir, idx, dir->vol, entry_name)) < 0) { free(entry_name); if (ret == -LTFS_NO_MEMORY) return -LTFS_NO_MEMORY; else return -1; } } else { ignore_unrecognized_tag(); entry_name = NULL; } if (!strcmp(name, "file") || (!strcmp(name, "directory") && !(!dir && idx->root))) { /* Make temporal hash table whose key is dentry name */ HASH_ADD_KEYPTR(hh, list, entry_name->name, strlen(entry_name->name), entry_name); if (errno == ENOMEM) { struct name_list *list_ptr, *list_tmp; HASH_ITER(hh, list, list_ptr, list_tmp) { HASH_DEL(list, list_ptr); free(list_ptr); } ltfsmsg(LTFS_ERR, "10001E", "_xml_parse_dir_contents: add key"); /* HP fix for double free when a tape with a large index file is mounted * on a host with low physical memory */ /*free(entry_name);*/ return -LTFS_NO_MEMORY; } } else {
void connection_handler::handle_messages() { detail::handling_messages hm(handling_messages_); // reset on exit bool bootstrapping = hpx::is_starting(); bool has_work = true; std::size_t k = 0; hpx::util::high_resolution_timer t; std::list<std::pair<int, MPI_Request> > close_requests; // We let the message handling loop spin for another 2 seconds to avoid the // costs involved with posting it to asio while(bootstrapping || has_work || (!has_work && t.elapsed() < 2.0)) { if(stopped_) break; // break the loop if someone requested to pause the parcelport if(!enable_parcel_handling_) break; // handle all send requests { hpx::lcos::local::spinlock::scoped_lock l(senders_mtx_); for( senders_type::iterator it = senders_.begin(); !stopped_ && enable_parcel_handling_ && it != senders_.end(); /**/) { if((*it)->done()) { it = senders_.erase(it); } else { ++it; } } has_work = !senders_.empty(); } // Send the pending close requests { hpx::lcos::local::spinlock::scoped_lock l(close_mtx_); typedef std::pair<int, int> pair_type; BOOST_FOREACH(pair_type p, pending_close_requests_) { header close_request = header::close(p.first, p.second); close_requests.push_back(std::make_pair(p.first, MPI_Request())); MPI_Isend( close_request.data(), // Data pointer close_request.data_size_, // Size close_request.type(), // MPI Datatype close_request.rank(), // Destination 0, // Tag communicator_, // Communicator &close_requests.back().second ); } pending_close_requests_.clear(); } // add new receive requests std::pair<bool, header> next(acceptor_.next_header()); if(next.first) { boost::shared_ptr<receiver> rcv; header h = next.second; receivers_tag_map_type & tag_map = receivers_map_[h.rank()]; receivers_tag_map_type::iterator jt = tag_map.find(h.tag()); if(jt != tag_map.end()) { rcv = jt->second; } else { rcv = boost::make_shared<receiver>( communicator_ , get_next_tag() , h.tag() , h.rank() , *this); tag_map.insert(std::make_pair(h.tag(), rcv)); } if(h.close_request()) { rcv->close(); } else { h.assert_valid(); if (static_cast<std::size_t>(h.size()) > this->get_max_message_size()) { // report this problem ... HPX_THROW_EXCEPTION(boost::asio::error::operation_not_supported, "mpi::connection_handler::handle_messages", "The size of this message exceeds the maximum inbound data size"); return; } if(rcv->async_read(h)) { #ifdef HPX_DEBUG receivers_type::iterator it = std::find(receivers_.begin(), receivers_.end(), rcv); HPX_ASSERT(it == receivers_.end()); #endif receivers_.push_back(rcv); } } } // handle all receive requests for(receivers_type::iterator it = receivers_.begin(); it != receivers_.end(); /**/) { boost::shared_ptr<receiver> rcv = *it; if(rcv->done()) { HPX_ASSERT(rcv->sender_tag() != -1); if(rcv->closing()) { receivers_tag_map_type & tag_map = receivers_map_[rcv->rank()]; receivers_tag_map_type::iterator jt = tag_map.find(rcv->sender_tag()); HPX_ASSERT(jt != tag_map.end()); tag_map.erase(jt); { hpx::lcos::local::spinlock::scoped_lock l(tag_mtx_); free_tags_.push_back(rcv->tag()); } } it = receivers_.erase(it); } else { ++it; } } if(!has_work) has_work = !receivers_.empty(); // handle completed close requests for( std::list<std::pair<int, MPI_Request> >::iterator it = close_requests.begin(); !stopped_ && enable_parcel_handling_ && it != close_requests.end(); ) { int completed = 0; MPI_Status status; int ret = 0; ret = MPI_Test(&it->second, &completed, &status); HPX_ASSERT(ret == MPI_SUCCESS); if(completed && status.MPI_ERROR != MPI_ERR_PENDING) { hpx::lcos::local::spinlock::scoped_lock l(tag_mtx_); free_tags_.push_back(it->first); it = close_requests.erase(it); } else { ++it; } } if(!has_work) has_work = !close_requests.empty(); if (bootstrapping) bootstrapping = hpx::is_starting(); if(has_work) { t.restart(); k = 0; } else { if(enable_parcel_handling_) { hpx::lcos::local::spinlock::yield(k); ++k; } } }
void connection_handler::handle_messages() { detail::handling_messages hm(handling_messages_); // reset on exit bool bootstrapping = hpx::is_starting(); bool has_work = true; std::size_t k = 0; hpx::util::high_resolution_timer t; std::list<std::pair<int, MPI_Request> > close_requests; // We let the message handling loop spin for another 2 seconds to avoid the // costs involved with posting it to asio while(bootstrapping || (!stopped_ && has_work) || (!has_work && t.elapsed() < 2.0)) { // break the loop if someone requested to pause the parcelport if(!enable_parcel_handling_) break; // handle all send requests { hpx::lcos::local::spinlock::scoped_lock l(senders_mtx_); for( senders_type::iterator it = senders_.begin(); !stopped_ && enable_parcel_handling_ && it != senders_.end(); /**/) { if((*it)->done()) { it = senders_.erase(it); } else { ++it; } } has_work = !senders_.empty(); } // Send the pending close requests { hpx::lcos::local::spinlock::scoped_lock l(close_mtx_); typedef std::pair<int, int> pair_type; BOOST_FOREACH(pair_type p, pending_close_requests_) { header close_request = header::close(p.first, p.second); close_requests.push_back(std::make_pair(p.first, MPI_Request())); MPI_Isend( close_request.data(), // Data pointer close_request.data_size_, // Size close_request.type(), // MPI Datatype close_request.rank(), // Destination 0, // Tag communicator_, // Communicator &close_requests.back().second ); } pending_close_requests_.clear(); } // add new receive requests std::pair<bool, header> next(acceptor_.next_header()); if(next.first) { boost::shared_ptr<receiver> rcv; receivers_rank_map_type::iterator jt = receivers_map_.find(next.second.rank()); if(jt != receivers_map_.end()) { receivers_tag_map_type::iterator kt = jt->second.find(next.second.tag()); if(kt != jt->second.end()) { if(next.second.close_request()) { hpx::lcos::local::spinlock::scoped_lock l(tag_mtx_); free_tags_.push_back(kt->second->tag()); jt->second.erase(kt); if(jt->second.empty()) { receivers_map_.erase(jt); } } else { rcv = kt->second; } } } if(!next.second.close_request()) { next.second.assert_valid(); if(!rcv) { rcv = boost::make_shared<receiver>(communicator_, get_next_tag()); } rcv->async_read(next.second, *this); receivers_.push_back(rcv); } } // handle all receive requests for( receivers_type::iterator it = receivers_.begin(); !stopped_ && enable_parcel_handling_ && it != receivers_.end(); /**/) { if((*it)->done(*this)) { HPX_ASSERT( !receivers_map_[(*it)->rank()][(*it)->sender_tag()] || receivers_map_[(*it)->rank()][(*it)->sender_tag()].get() == it->get() ); receivers_map_[(*it)->rank()][(*it)->sender_tag()] = *it; it = receivers_.erase(it); } else { ++it; } } if(!has_work) has_work = !receivers_.empty(); // handle completed close requests for( std::list<std::pair<int, MPI_Request> >::iterator it = close_requests.begin(); !stopped_ && enable_parcel_handling_ && it != close_requests.end(); ) { int completed = 0; MPI_Status status; int ret = 0; ret = MPI_Test(&it->second, &completed, &status); HPX_ASSERT(ret == MPI_SUCCESS); if(completed && status.MPI_ERROR != MPI_ERR_PENDING) { hpx::lcos::local::spinlock::scoped_lock l(tag_mtx_); free_tags_.push_back(it->first); it = close_requests.erase(it); } else { ++it; } } if(!has_work) has_work = !close_requests.empty(); if (bootstrapping) bootstrapping = hpx::is_starting(); if(has_work) { t.restart(); k = 0; } else { if(enable_parcel_handling_) { hpx::lcos::local::spinlock::yield(k); ++k; } } }