- try {
- if (mountPoint != null) {
- normalizedII = new DataNormalizer(mountPoint.getSchemaContext()).toNormalized(iiWithData
- .getInstanceIdentifier());
- broker.commitConfigurationDataPut(mountPoint, normalizedII, datastoreNormalizedNode).get();
- } else {
- normalizedII = controllerContext.toNormalized(iiWithData.getInstanceIdentifier());
- broker.commitConfigurationDataPut(normalizedII, datastoreNormalizedNode).get();
+ /*
+ * There is a small window where another write transaction could be updating the same data
+ * simultaneously and we get an OptimisticLockFailedException. This error is likely
+ * transient and The WriteTransaction#submit API docs state that a retry will likely
+ * succeed. So we'll try again if that scenario occurs. If it fails a third time then it
+ * probably will never succeed so we'll fail in that case.
+ *
+ * By retrying we're attempting to hide the internal implementation of the data store and
+ * how it handles concurrent updates from the restconf client. The client has instructed us
+ * to put the data and we should make every effort to do so without pushing optimistic lock
+ * failures back to the client and forcing them to handle it via retry (and having to
+ * document the behavior).
+ */
+ int tries = 2;
+ while(true) {
+ try {
+ if (mountPoint != null) {
+ broker.commitConfigurationDataPut(mountPoint, normalizedII,
+ datastoreNormalizedNode).checkedGet();
+ } else {
+ broker.commitConfigurationDataPut(normalizedII,
+ datastoreNormalizedNode).checkedGet();
+ }
+
+ break;
+ } catch (TransactionCommitFailedException e) {
+ if(e instanceof OptimisticLockFailedException) {
+ if(--tries <= 0) {
+ LOG.debug("Got OptimisticLockFailedException on last try - failing");
+ throw new RestconfDocumentedException(e.getMessage(), e, e.getErrorList());
+ }
+
+ LOG.debug("Got OptimisticLockFailedException - trying again");
+ } else {
+ throw new RestconfDocumentedException(e.getMessage(), e, e.getErrorList());
+ }