/** * Complete a {@link WriteEntry} that was created by {@link #begin()} then wait until the * read point catches up to our write. * * At the end of this call, the global read point is at least as large as the write point * of the passed in WriteEntry. Thus, the write is visible to MVCC readers. */ public void completeAndWait(WriteEntry e) { if (!complete(e)) { waitForRead(e); } }
@Test public void testSimpleMvccOps() { MultiVersionConcurrencyControl mvcc = new MultiVersionConcurrencyControl(); long readPoint = mvcc.getReadPoint(); MultiVersionConcurrencyControl.WriteEntry writeEntry = mvcc.begin(); mvcc.completeAndWait(writeEntry); assertEquals(readPoint + 1, mvcc.getReadPoint()); writeEntry = mvcc.begin(); // The write point advances even though we may have 'failed'... call complete on fail. mvcc.complete(writeEntry); assertEquals(readPoint + 2, mvcc.getWritePoint()); } }
mvcc.complete(writeEntry);
if (writeEntry != null) mvcc.complete(writeEntry); if (rowLock != null) { rowLock.release();
} finally { if (writeEntry != null) mvcc.complete(writeEntry); if (locked) { this.updatesLock.readLock().unlock();
} catch (IOException ioe) { if (walKey != null && walKey.getWriteEntry() != null) { mvcc.complete(walKey.getWriteEntry());
@Test public void testSimpleMvccOps() { MultiVersionConcurrencyControl mvcc = new MultiVersionConcurrencyControl(); long readPoint = mvcc.getReadPoint(); MultiVersionConcurrencyControl.WriteEntry writeEntry = mvcc.begin(); mvcc.completeAndWait(writeEntry); assertEquals(readPoint + 1, mvcc.getReadPoint()); writeEntry = mvcc.begin(); // The write point advances even though we may have 'failed'... call complete on fail. mvcc.complete(writeEntry); assertEquals(readPoint + 2, mvcc.getWritePoint()); } }
/** * Complete a {@link WriteEntry} that was created by {@link #begin()} then wait until the * read point catches up to our write. * * At the end of this call, the global read point is at least as large as the write point * of the passed in WriteEntry. Thus, the write is visible to MVCC readers. */ public void completeAndWait(WriteEntry e) { complete(e); waitForRead(e); }
/** * Will block until a write entry has been assigned by they WAL subsystem. * @return A WriteEntry gotten from local WAL subsystem. Must be completed by calling * mvcc#complete or mvcc#completeAndWait. * @throws InterruptedIOException * @see * #setWriteEntry(org.apache.hadoop.hbase.regionserver.MultiVersionConcurrencyControl.WriteEntry) */ @InterfaceAudience.Private // For internal use only. public MultiVersionConcurrencyControl.WriteEntry getWriteEntry() throws InterruptedIOException { try { this.seqNumAssignedLatch.await(); } catch (InterruptedException ie) { // If interrupted... clear out our entry else we can block up mvcc. MultiVersionConcurrencyControl mvcc = getMvcc(); LOG.debug("mvcc=" + mvcc + ", writeEntry=" + this.writeEntry); if (mvcc != null) { if (this.writeEntry != null) { mvcc.complete(this.writeEntry); } } InterruptedIOException iie = new InterruptedIOException(); iie.initCause(ie); throw iie; } return this.writeEntry; }
if (walKey != null) mvcc.complete(walKey.getWriteEntry()); } else { if (walKey != null) mvcc.completeAndWait(walKey.getWriteEntry());
/** * Method to safely get the next sequence number. * @return Next sequence number unassociated with any actual edit. * @throws IOException */ @VisibleForTesting protected long getNextSequenceId(final WAL wal) throws IOException { // TODO: For review. Putting an empty edit in to get a sequenceid out will not work if the // WAL is banjaxed... if it has gotten an exception and the WAL has not yet been rolled or // aborted. In this case, we'll just get stuck here. For now, until HBASE-12751, just have // a timeout. May happen in tests after we tightened the semantic via HBASE-14317. // Also, the getSequenceId blocks on a latch. There is no global list of outstanding latches // so if an abort or stop, there is no way to call them in. WALKey key = this.appendEmptyEdit(wal); mvcc.complete(key.getWriteEntry()); return key.getSequenceId(this.maxWaitForSeqId); }
if (doRollBackMemstore) { rollbackMemstore(allKVs); if (we != null) mvcc.complete(we); } else if (we != null) { mvcc.completeAndWait(we);
private static long writeMarker(final WAL wal, final HTableDescriptor htd, final HRegionInfo hri, final WALEdit edit, final MultiVersionConcurrencyControl mvcc, final boolean sync) throws IOException { // TODO: Pass in current time to use? WALKey key = new HLogKey(hri.getEncodedNameAsBytes(), hri.getTable(), System.currentTimeMillis(), mvcc); // Add it to the log but the false specifies that we don't need to add it to the memstore long trx = MultiVersionConcurrencyControl.NONE; try { trx = wal.append(htd, hri, key, edit, false); if (sync) wal.sync(trx); } finally { // If you get hung here, is it a real WAL or a mocked WAL? If the latter, you need to // trip the latch that is inside in getWriteEntry up in your mock. See down in the append // called from onEvent in FSHLog. MultiVersionConcurrencyControl.WriteEntry we = key.getWriteEntry(); if (mvcc != null && we != null) mvcc.complete(we); } return trx; } }
mvcc.complete(writeEntry); writeEntry = null;
/** * Append a faked WALEdit in order to get a long sequence number and wal syncer will just ignore * the WALEdit append later. * @param wal * @return Return the key used appending with no sync and no append. * @throws IOException */ private WALKey appendEmptyEdit(final WAL wal) throws IOException { // we use HLogKey here instead of WALKey directly to support legacy coprocessors. @SuppressWarnings("deprecation") WALKey key = new HLogKey(getRegionInfo().getEncodedNameAsBytes(), getRegionInfo().getTable(), WALKey.NO_SEQUENCE_ID, 0, null, HConstants.NO_NONCE, HConstants.NO_NONCE, getMVCC()); // Call append but with an empty WALEdit. The returned sequence id will not be associated // with any edit and we can be sure it went in after all outstanding appends. try { wal.append(getTableDesc(), getRegionInfo(), key, WALEdit.EMPTY_WALEDIT, false); } catch (Throwable t) { // If exception, our mvcc won't get cleaned up by client, so do it here. getMVCC().complete(key.getWriteEntry()); } return key; }
if (writeEntry != null) mvcc.complete(writeEntry); } else if (writeEntry != null) { mvcc.completeAndWait(writeEntry);