private static Item GetCurrentItem(JsonOperationContext ctx, TableValueReader reader) { int size; return(new Item { Data = new BlittableJsonReaderObject(reader.Read(2, out size), size, ctx), Key = Encoding.UTF8.GetString(reader.Read(1, out size), size), Etag = Bits.SwapBytes(*(long *)reader.Read(3, out size)) }); }
public long ReadLastEtag(TransactionOperationContext ctx) { var table = ctx.Transaction.InnerTransaction.OpenTable(_itemsSchema, "Items"); var itemsFromBackwards = table.SeekBackwardFrom(_itemsSchema.FixedSizeIndexes[EtagIndexName], long.MaxValue); var reader = itemsFromBackwards.FirstOrDefault(); if (reader == null) { return(0); } int size; return(Bits.SwapBytes(*(long *)reader.Read(3, out size))); }
public unsafe int GetHashCode(StringSegment str) { if (_buffer == null || _buffer.Length < str.Length) { _buffer = new char[Bits.NextPowerOf2(str.Length)]; } for (int i = 0; i < str.Length; i++) { _buffer[i] = char.ToUpperInvariant(str.String[str.Start + i]); } fixed(char *p = _buffer) { return((int)Hashing.XXHash32.CalculateInline((byte *)p, str.Length * sizeof(char))); } }
public Tuple <BlittableJsonReaderObject, long> ReadWithEtag(TransactionOperationContext ctx, string id) { var items = ctx.Transaction.InnerTransaction.OpenTable(_itemsSchema, "Items"); TableValueReader reader; Slice key; using (Slice.From(ctx.Allocator, id.ToLowerInvariant(), out key)) { reader = items.ReadByKey(key); } if (reader == null) { return(null); } int size; var ptr = reader.Read(2, out size); return(Tuple.Create(new BlittableJsonReaderObject(ptr, size, ctx), Bits.SwapBytes(*(long *)reader.Read(3, out size)))); }
public unsafe int GetHashCode(StringSegment str) { if (_buffer == null || _buffer.Length < str.Length) { _buffer = new char[Bits.NextPowerOf2(str.Length)]; } for (int i = 0; i < str.Length; i++) { _buffer[i] = char.ToUpperInvariant(str.Buffer[str.Offset + i]); } fixed(char *p = _buffer) { //PERF: JIT will remove the corresponding line based on the target architecture using dead code removal. if (IntPtr.Size == 4) { return((int)Hashing.XXHash32.CalculateInline((byte *)p, str.Length * sizeof(char))); } return((int)Hashing.XXHash64.CalculateInline((byte *)p, (ulong)str.Length * sizeof(char))); } }
public long Write(TransactionOperationContext ctx, string id, BlittableJsonReaderObject doc, long?expectedEtag = null) { TrackChangeAfterTransactionCommit(ctx, "Write", id); var newEtag = _lastEtag + 1; Slice idAsSlice; Slice loweredId; using (Slice.From(ctx.Allocator, id, out idAsSlice)) using (Slice.From(ctx.Allocator, id.ToLowerInvariant(), out loweredId)) { var newEtagBigEndian = Bits.SwapBytes(newEtag); var itemTable = ctx.Transaction.InnerTransaction.OpenTable(_itemsSchema, "Items"); var oldValue = itemTable.ReadByKey(loweredId); if (oldValue == null) { if (expectedEtag != null && expectedEtag != 0) { throw new ConcurrencyException( $"Server store item {id} does not exists, but Write was called with etag {expectedEtag}. Optimistic concurrency violation, transaction will be aborted.") { ExpectedETag = (long)expectedEtag }; } itemTable.Insert(new TableValueBuilder { loweredId, idAsSlice, { doc.BasePointer, doc.Size }, {&newEtagBigEndian, sizeof(long) } }); } else { int size; var test = GetCurrentItem(ctx, oldValue); var oldEtag = Bits.SwapBytes(*(long *)oldValue.Read(3, out size)); if (expectedEtag != null && oldEtag != expectedEtag) { throw new ConcurrencyException( $"Server store item {id} has etag {oldEtag}, but Write was called with etag {expectedEtag}. Optimistic concurrency violation, transaction will be aborted.") { ActualETag = oldEtag, ExpectedETag = (long)expectedEtag } } ; itemTable.Update(oldValue.Id, new TableValueBuilder { loweredId, idAsSlice, { doc.BasePointer, doc.Size }, {&newEtagBigEndian, sizeof(long) } }); } } _lastEtag++; return(newEtag); }
public void Initialize() { _shutdownNotification = new CancellationTokenSource(); AbstractLowMemoryNotification.Initialize(ServerShutdown, Configuration); if (_logger.IsInfoEnabled) { _logger.Info("Starting to open server store for " + (Configuration.Core.RunInMemory ? "<memory>" : Configuration.Core.DataDirectory)); } var options = Configuration.Core.RunInMemory ? StorageEnvironmentOptions.CreateMemoryOnly(Configuration.Core.DataDirectory) : StorageEnvironmentOptions.ForPath(System.IO.Path.Combine(Configuration.Core.DataDirectory, "System")); options.SchemaVersion = 2; try { StorageEnvironment.MaxConcurrentFlushes = Configuration.Storage.MaxConcurrentFlushes; _env = new StorageEnvironment(options); using (var tx = _env.WriteTransaction()) { tx.DeleteTree("items");// note the different casing, we remove the old items tree _itemsSchema.Create(tx, "Items", 16); tx.Commit(); } using (var tx = _env.ReadTransaction()) { var table = tx.OpenTable(_itemsSchema, "Items"); var itemsFromBackwards = table.SeekBackwardFrom(_itemsSchema.FixedSizeIndexes[EtagIndexName], long.MaxValue); var reader = itemsFromBackwards.FirstOrDefault(); if (reader == null) { _lastEtag = 0; } else { int size; _lastEtag = Bits.SwapBytes(*(long *)reader.Read(3, out size)); } } } catch (Exception e) { if (_logger.IsOperationsEnabled) { _logger.Operations( "Could not open server store for " + (Configuration.Core.RunInMemory ? "<memory>" : Configuration.Core.DataDirectory), e); } options.Dispose(); throw; } ContextPool = new TransactionContextPool(_env); _timer = new Timer(IdleOperations, null, _frequencyToCheckForIdleDatabases, TimeSpan.FromDays(7)); Alerts.Initialize(_env, ContextPool); DatabaseInfoCache.Initialize(_env, ContextPool); LicenseStorage.Initialize(_env, ContextPool); }