Source:
<code>@Override public void addMeta(final int typeId, final BinaryType newMeta, boolean failIfUnregistered) throws BinaryObjectException { assert newMeta != null; assert newMeta instanceof BinaryTypeImpl; BinaryMetadata newMeta0 = ((BinaryTypeImpl)newMeta).metadata(); try { BinaryMetadataHolder metaHolder = metadataLocCache.get(typeId); BinaryMetadata oldMeta = metaHolder != null ? metaHolder.metadata() : null; Set<Integer> changedSchemas = new LinkedHashSet<>(); BinaryMetadata mergedMeta = BinaryUtils.mergeMetadata(oldMeta, newMeta0, changedSchemas); if (mergedMeta == oldMeta) <START> while (true) { <END> if (metaHolder.pendingVersion() == metaHolder.acceptedVersion()) return; metaHolder = metadataLocCache.get(typeId); } if (failIfUnregistered) throw new UnregisteredBinaryTypeException( "Attempted to update binary metadata inside a critical synchronization block (will be " + "automatically retried). This exception must not be wrapped to any other exception class. " + "If you encounter this exception outside of EntryProcessor, please report to Apache Ignite " + "dev-list.", typeId, mergedMeta); long t0 = System.nanoTime(); GridFutureAdapter<MetadataUpdateResult> fut = transport.requestMetadataUpdate(mergedMeta); MetadataUpdateResult res = fut.get(); if (log.isDebugEnabled()) { IgniteInternalTx tx = ctx.cache().context().tm().tx(); log.debug("Completed metadata update [typeId=" + typeId + ", typeName=" + newMeta.typeName() + ", changedSchemas=" + changedSchemas + ", waitTime=" + MILLISECONDS.convert(System.nanoTime() - t0, NANOSECONDS) + "ms" + ", holder=" + metaHolder + ", fut=" + fut + ", tx=" + CU.txString(tx) + ']'); } assert res != null; if (res.rejected()) throw res.error(); } catch (IgniteCheckedException e) { throw new BinaryObjectException("Failed to update meta data for type: " + newMeta.typeName(), e); } }</code><technical_language>Instead of spinning in loop BinaryMetadataTransport::awaitMetadataUpdate method wait metaHolder.pendingVersion is accepted cluster</technical_language>

Target:
@Override public void addMeta(final int typeId, final BinaryType newMeta, boolean failIfUnregistered) throws BinaryObjectException { assert newMeta != null; assert newMeta instanceof BinaryTypeImpl; BinaryMetadata newMeta0 = ((BinaryTypeImpl)newMeta).metadata(); try { BinaryMetadataHolder metaHolder = metadataLocCache.get(typeId); BinaryMetadata oldMeta = metaHolder != null ? metaHolder.metadata() : null; Set<Integer> changedSchemas = new LinkedHashSet<>(); BinaryMetadata mergedMeta = BinaryUtils.mergeMetadata(oldMeta, newMeta0, changedSchemas); if (mergedMeta == oldMeta) { if (metaHolder.pendingVersion() != metaHolder.acceptedVersion()) { GridFutureAdapter<MetadataUpdateResult> fut = transport.awaitMetadataUpdate(typeId, metaHolder.pendingVersion()); fut.get(); } return; } if (failIfUnregistered) throw new UnregisteredBinaryTypeException( "Attempted to update binary metadata inside a critical synchronization block (will be " + "automatically retried). This exception must not be wrapped to any other exception class. " + "If you encounter this exception outside of EntryProcessor, please report to Apache Ignite " + "dev-list.", typeId, mergedMeta); long t0 = System.nanoTime(); GridFutureAdapter<MetadataUpdateResult> fut = transport.requestMetadataUpdate(mergedMeta); MetadataUpdateResult res = fut.get(); if (log.isDebugEnabled()) { IgniteInternalTx tx = ctx.cache().context().tm().tx(); log.debug("Completed metadata update [typeId=" + typeId + ", typeName=" + newMeta.typeName() + ", changedSchemas=" + changedSchemas + ", waitTime=" + MILLISECONDS.convert(System.nanoTime() - t0, NANOSECONDS) + "ms" + ", holder=" + metaHolder + ", fut=" + fut + ", tx=" + CU.txString(tx) + ']'); } assert res != null; if (res.rejected()) throw res.error(); } catch (IgniteCheckedException e) { throw new BinaryObjectException("Failed to update metadata for type: " + newMeta.typeName(), e); } }