protected virtual unsafe void OnLogAppend(DirectBuffer buffer) { var writerPid = buffer.ReadInt64(DataHeaderFlyweight.RESERVED_VALUE_OFFSET); var messageBuffer = new DirectBuffer(buffer.Length - DataHeaderFlyweight.HEADER_LENGTH, buffer.Data + DataHeaderFlyweight.HEADER_LENGTH); var header = *(CommandHeader *)(messageBuffer.Data); var uuid = header.SeriesId; IAcceptCommand series; if ( writerPid != Pid // ignore our own messages && _openSeries.TryGetValue(uuid, out series) // ignore messages for closed series ) { if (header.CommandType == CommandType.Broadcast) { OnBroadcast?.Invoke(messageBuffer); } else { series.ApplyCommand(messageBuffer); } } }
/// <summary> /// Deletes up to (but not including) this value for the key. /// </summary> /// <param name="tx">transaction</param> /// <param name="db">database</param> /// <param name="key">key</param> /// <param name="value">Value (or part of the value) to which the data will be deleted</param> /// <param name="firstValue">First value to position to the beginning of dupes. Even if first value is bigger it is OK.</param> /// <returns></returns> public static unsafe bool DeleteUpToValue(this Transaction tx, Database db, long key, long value, long firstValue = 0L) { int deletedCount = 0; using (var c = db.OpenCursor(tx)) { try { byte *keyptr = (byte *)Unsafe.AsPointer(ref key); byte *valptr = (byte *)Unsafe.AsPointer(ref value); byte *firstvalptr = (byte *)Unsafe.AsPointer(ref firstValue); var keydb = new DirectBuffer(sizeof(long), keyptr); var valdb = new DirectBuffer(sizeof(long), firstvalptr); c.TryFindDup(Lookup.LE, ref keydb, ref valdb); while (c.Delete(false)) { deletedCount++; if (!c.TryGet(ref keydb, ref valdb, CursorGetOption.GetBothRange) || valdb.IsEmpty) { break; // empty now } var currentValue = valdb.ReadInt64(0); if (currentValue == value) { break; } } return(true); } catch (Exception e) { throw new DeleteUpToException( $"Failed after deleting {deletedCount} records." , e); } } }
/** * Get the value of the correlation ID for this log. * * @param logMetaDataBuffer containing the meta data. * @return the value of the correlation ID used for this log. */ public static long CorrelationId(DirectBuffer logMetaDataBuffer) { return(logMetaDataBuffer.ReadInt64(LOG_CORRELATION_ID_OFFSET)); }
protected unsafe void OnLogAppend(DirectBuffer buffer) { var writerPid = buffer.ReadInt64(DataHeaderFlyweight.RESERVED_VALUE_OFFSET); var messageBuffer = new DirectBuffer(buffer.Length - DataHeaderFlyweight.HEADER_LENGTH, buffer.Data + DataHeaderFlyweight.HEADER_LENGTH); var header = *(MessageHeader *)(messageBuffer.Data); var seriesId = header.UUID; var messageType = header.MessageType; switch (messageType) { case MessageType.ConductorMessage: // this message could be sent only by a process that // thinks it is a conductor var currentConductor = writerPid; if (Math.Abs(currentConductor) != Pid) { // negative writerPid must be sent on conductor repo dispose _isConductor = writerPid <= 0 && TryBecomeConductor(); } break; case MessageType.WriteRequest: if (_isConductor) { BeginAcquireWriteLock(seriesId, writerPid); } break; case MessageType.CurrentWriter: // new writer is sent by a conductor in response TaskCompletionSource <long> temp; if (_writerRequestsOustanding.TryGetValue(seriesId, out temp)) { temp.SetResult(writerPid); } break; case MessageType.Subscribe: if (_isConductor) { IAcceptCommand tempAcceptCommand; if (_openStreams.TryGetValue(seriesId, out tempAcceptCommand)) { tempAcceptCommand.Flush(); } BeginSyncronizeSeries(seriesId, header.Version); } break; case MessageType.Synced: TaskCompletionSource <byte> temp2; if (_syncRequestsOustanding.TryGetValue(seriesId, out temp2)) { temp2.SetResult(1); } break; default: IAcceptCommand acceptCommand; if (writerPid != Pid && // ignore our own messages _openStreams.TryGetValue(seriesId, out acceptCommand) // ignore messages for closed series ) { acceptCommand.ApplyCommand(messageBuffer); } break; } }