public static bool StillAlive(Key* self, ulong sequence) { if (self == null) return false; if ((self->Header & Entry.FLAGS_UNREACHABLE) != 0) { // we have been marked as dead var value = self->Values; if (value == null) return false; // check if the last value is a deletion? if (value->Sequence <= sequence && (value->Header & Value.FLAGS_DELETION) != 0) { // it is deleted return false; } } return true; }
public async Task WriteLevelAsync(int level, IntPtr[] segment, CancellationToken ct) { ct.ThrowIfCancellationRequested(); if (m_jumpTable[level].Value > 0) { throw new InvalidOperationException("The level has already be written to this snapshot"); } var levelStart = checked(m_file.Length + (uint)m_writer.Position); //Console.WriteLine("## level " + level + " starts at " + levelStart); //TODO: ensure that we start on a PAGE? //Console.WriteLine("> Writing level " + level); // "LVL_" m_writer.WriteFixed32(SnapshotFormat.LEVEL_MAGIC_NUMBER); // Level Flags m_writer.WriteFixed32(0); //TODO: flags! // Level ID m_writer.WriteFixed32((uint)level); // Item count (always 2^level) m_writer.WriteFixed32((uint)segment.Length); for (int i = 0; i < segment.Length; i++) { unsafe { #if __MonoCS__ var valuePointer =new IntPtr((void*) MemoryDatabaseHandler.ResolveValueAtVersion(segment[i], m_sequence)); if (valuePointer == IntPtr.Zero) continue; Value value = new Value(); Marshal.PtrToStructure(valuePointer, value); var keyPointer = new IntPtr((void*)segment[i]); Key key = new Key(); Marshal.PtrToStructure(keyPointer, key); Contract.Assert(key.Size <= MemoryDatabaseHandler.MAX_KEY_SIZE); // Key Size uint size = key.Size; m_writer.WriteVarint32(size); m_writer.WriteBytesUnsafe(&(key.Data), (int)size); // Value m_writer.WriteVarint64(value.Sequence); // sequence size = value.Size; if (size == 0) { // empty key m_writer.WriteByte(0); } else { m_writer.WriteVarint32(size); // value size m_writer.WriteBytesUnsafe(&(value.Data), (int)size); // value data } #else Value* value = MemoryDatabaseHandler.ResolveValueAtVersion(segment[i], m_sequence); if (value == null) { continue; } Key* key = (Key*)segment[i]; //.ToPointer(); Contract.Assert(key != null && key->Size <= MemoryDatabaseHandler.MAX_KEY_SIZE); // Key Size uint size = key->Size; m_writer.WriteVarint32(size); m_writer.WriteBytesUnsafe(&(key->Data), (int)size); // Value m_writer.WriteVarint64(value->Sequence); // sequence size = value->Size; if (size == 0) { // empty key m_writer.WriteByte(0); } else { m_writer.WriteVarint32(size); // value size m_writer.WriteBytesUnsafe(&(value->Data), (int)size); // value data } #endif } if (m_writer.Position >= SnapshotFormat.FLUSH_SIZE) { //Console.WriteLine("> partial flush (" + writer.Position + ")"); int written = await m_file.WriteCompletePagesAsync(m_writer.Buffer, m_writer.Position, ct).ConfigureAwait(false); if (written > 0) m_writer.Flush(written); } } m_writer.WriteFixed32(uint.MaxValue); //TODO: CRC? (would need to be computed on the fly, because we don't have the full slice in memory probably) m_writer.WriteFixed32(0); var levelEnd = checked(m_file.Length + (uint)m_writer.Position); m_jumpTable[level] = new KeyValuePair<ulong, ulong>(levelStart, levelEnd - levelStart); //Console.WriteLine("## level " + level + " ends at " + levelEnd); // optional padding to fill the rest of the page PadPageIfNeeded(SnapshotFormat.PAGE_SIZE, (byte)(0xFC - level)); }
/// <summary>Return the address of the following value in the heap</summary> internal static Key* WalkNext(Key* self) { Contract.Requires(self != null && Entry.GetObjectType(self) == EntryType.Key); return (Key*)Entry.Align((byte*)self + Key.SizeOf + self->Size); }
public static bool IsDisposed(Key* self) { return (self->Header & Entry.FLAGS_DISPOSED) != 0; }
public static USlice GetData(Key* self) { if (self == null) return default(USlice); Contract.Assert((self->Header & Entry.FLAGS_DISPOSED) == 0, "Attempt to read a key that was disposed"); return new USlice(&(self->Data), self->Size); }