/// <summary> /// Initializes a new instance of the <see cref="PsiStoreReader"/> class. /// This provides a fast way to create a reader, /// by reusing the metadata and index already loaded by an existing store reader. /// </summary> /// <param name="other">Another reader pointing to the same store.</param> public PsiStoreReader(PsiStoreReader other) { this.Name = other.Name; this.Path = other.Path; this.AutoOpenAllStreams = other.AutoOpenAllStreams; this.messageReader = new MessageReader(PsiStoreCommon.GetDataFileName(this.Name), this.Path); this.largeMessageReader = new MessageReader(PsiStoreCommon.GetLargeDataFileName(this.Name), this.Path); this.indexCache = other.indexCache.AddRef(); this.metadataCache = other.metadataCache.AddRef(); }
public MetadataCache(string name, string path, Action <IEnumerable <Metadata>, RuntimeInfo> entriesAdded) { this.name = name; this.path = path; this.catalogReader = new InfiniteFileReader(path, PsiStoreCommon.GetCatalogFileName(name)); this.entriesAdded = entriesAdded; // assume v0 for backwards compat. Update will fix this up if the file is newer. this.runtimeVersion = new RuntimeInfo(0); this.Update(); }
/// <summary> /// Initializes a new instance of the <see cref="PsiStoreReader"/> class. /// </summary> /// <param name="name">The name of the application that generated the persisted files, or the root name of the files.</param> /// <param name="path">The directory in which the main persisted file resides or will reside, or null to create a volatile data store.</param> /// <param name="metadataUpdateHandler">Delegate to call.</param> /// <param name="autoOpenAllStreams">Automatically open all streams.</param> public PsiStoreReader(string name, string path, Action <IEnumerable <Metadata>, RuntimeInfo> metadataUpdateHandler, bool autoOpenAllStreams = false) { this.Name = name; this.Path = PsiStore.GetPathToLatestVersion(name, path); this.AutoOpenAllStreams = autoOpenAllStreams; // open the data readers this.messageReader = new MessageReader(PsiStoreCommon.GetDataFileName(this.Name), this.Path); this.largeMessageReader = new MessageReader(PsiStoreCommon.GetLargeDataFileName(this.Name), this.Path); this.indexCache = Shared.Create(new PageIndexCache(name, this.Path)); this.metadataCache = Shared.Create(new MetadataCache(name, this.Path, metadataUpdateHandler)); }
/// <summary> /// Initializes a new instance of the <see cref="PsiStoreWriter"/> class. /// </summary> /// <param name="name">The name of the application that generated the persisted files, or the root name of the files.</param> /// <param name="path">The directory in which to create the partition, or null to create a volatile data store.</param> /// <param name="createSubdirectory">If true, a numbered sub-directory is created for this store.</param> public PsiStoreWriter(string name, string path, bool createSubdirectory = true) { this.name = name; if (path != null) { int id = 0; this.path = System.IO.Path.GetFullPath(path); if (createSubdirectory) { // if the root directory already exists, look for the next available id if (Directory.Exists(this.path)) { var existingIds = Directory.EnumerateDirectories(this.path, this.name + ".????") .Select(d => d.Split('.').Last()) .Where( n => { int i; return(int.TryParse(n, out i)); }) .Select(n => int.Parse(n)); id = (existingIds.Count() == 0) ? 0 : existingIds.Max() + 1; } this.path = System.IO.Path.Combine(this.path, $"{this.name}.{id:0000}"); } if (!Directory.Exists(this.path)) { Directory.CreateDirectory(this.path); } } this.catalogWriter = new InfiniteFileWriter(this.path, PsiStoreCommon.GetCatalogFileName(this.name), CatalogExtentSize); this.pageIndexWriter = new InfiniteFileWriter(this.path, PsiStoreCommon.GetIndexFileName(this.name), IndexExtentSize); this.writer = new MessageWriter(PsiStoreCommon.GetDataFileName(this.name), this.path); // write the first index entry this.UpdatePageIndex(0, default(Envelope)); }
/// <summary> /// Indicates whether the specified data store has an active writer. /// </summary> /// <param name="storeName">The store name.</param> /// <param name="storePath">The store path.</param> /// <returns>Returns true if there is an active data file writer to this store.</returns> public static bool IsStoreLive(string storeName, string storePath) { if (!Mutex.TryOpenExisting(InfiniteFileWriter.ActiveWriterMutexName(storePath, PsiStoreCommon.GetCatalogFileName(storeName)), out Mutex writerActiveMutex)) { return(false); } writerActiveMutex.Dispose(); return(true); }
/// <summary> /// Creates a stream to write messages to. /// </summary> /// <param name="streamId">The id of the stream, unique for this store. All messages with this stream id will be written to this stream.</param> /// <param name="streamName">The name of the stream. This name can be later used to open the stream for reading.</param> /// <param name="indexed">Indicates whether the stream is indexed or not. Indexed streams have a small index entry in the main data file and the actual message body in a large data file.</param> /// <param name="typeName">A name identifying the type of the messages in this stream. This is usually a fully-qualified type name or a data contract name, but can be anything that the caller wants.</param> /// <returns>The complete metadata for the stream just created.</returns> public PsiStreamMetadata OpenStream(int streamId, string streamName, bool indexed, string typeName) { if (this.metadata.ContainsKey(streamId)) { throw new InvalidOperationException($"The stream id {streamId} has already been registered with this writer."); } var meta = new PsiStreamMetadata(streamName, streamId, typeName); meta.OpenedTime = Time.GetCurrentTime(); meta.IsPersisted = true; meta.IsIndexed = indexed; meta.PartitionName = this.name; meta.PartitionPath = this.path; this.metadata[streamId] = meta; this.WriteToCatalog(meta); // make sure we have a large file if needed if (indexed) { this.largeMessageWriter = this.largeMessageWriter ?? new MessageWriter(PsiStoreCommon.GetLargeDataFileName(this.name), this.path); } return(meta); }
public PageIndexCache(string name, string path) { this.indexReader = new InfiniteFileReader(path, PsiStoreCommon.GetIndexFileName(name)); }