diff --git a/docs/blob-provider.md b/docs/blob-provider.md index b2c94c325..afdd8bee2 100644 --- a/docs/blob-provider.md +++ b/docs/blob-provider.md @@ -52,7 +52,7 @@ If you are working in the context of the sensenet Content Repository, you do not ## Built-in blob provider -The built-in blob provider will always be there as a fallback. Currently it supports storing files in the database either in a regular *varbinary* column or in a *FILESTREAM* column. +The built-in blob provider will always be there as a fallback. Currently it supports storing files in the database in a regular *varbinary* column. ## Custom blob provider diff --git a/src/BlobStorage/BlobStorageConfiguration.cs b/src/BlobStorage/BlobStorageConfiguration.cs deleted file mode 100644 index ffe4bfceb..000000000 --- a/src/BlobStorage/BlobStorageConfiguration.cs +++ /dev/null @@ -1,53 +0,0 @@ -using System; -using SenseNet.Configuration; - -namespace SenseNet.ContentRepository.Storage -{ - /// - /// Provides configuration values needed by the blob storage. Obsolete class. - /// - [Obsolete("After V6.5 PATCH 9: Use the Configuration.BlobStorage class instead.")] - public static class BlobStorageConfiguration - { - /// - /// Size of chunks (in bytes) that are sent to the server by the upload control. It is also taken into - /// account when computing the size of inner buffers and caches. - /// - public static int BinaryChunkSize => BlobStorage.BinaryChunkSize; - - /// - /// Size (in bytes) of the binary buffer used by internal streams when serving files from - /// the database or the file system. The purpose of this cache is to serve requests faster - /// and to reduce the number of SQL connections. - /// - public static int BinaryBufferSize => BlobStorage.BinaryBufferSize; - - /// - /// Maximum file size (in bytes) that should be cached after loading a binary value. Smaller files - /// will by placed into the cache, larger files will always be served from the blob storage directly. - /// - public static int BinaryCacheSize => BlobStorage.BinaryCacheSize; - - /// - /// Minimum size limit (in bytes) for binary data to be stored in a SQL FileStream column. - /// Files smaller or equal this size will be stored in the database. Bigger files will go - /// to a FileStream column if the feature is enabled in the database. - /// If you set this to 0, all files will go to the filestream column. - /// In case of a huge value everything will remain in the db. - /// - public static int MinimumSizeForFileStreamInBytes => BlobStorage.MinimumSizeForFileStreamInBytes; - - /// - /// Minimum size limit (in bytes) for binary data to be stored in the external blob storage. - /// Files under this size will be stored in the database. If you set this to 0, all files - /// will go to the external storage. In case of a huge value everything will remain in the db. - /// - public static int MinimumSizeForBlobProviderInBytes => BlobStorage.MinimumSizeForBlobProviderInBytes; - - /// - /// Whether the FileStream feature is enabled in the system or not. - /// Computed property, not possible to configure. - /// - public static bool FileStreamEnabled => BlobStorage.FileStreamEnabled; - } -} diff --git a/src/BlobStorage/Configuration/BlobStorage.cs b/src/BlobStorage/Configuration/BlobStorage.cs index 0c39dc40e..fcb72652c 100644 --- a/src/BlobStorage/Configuration/BlobStorage.cs +++ b/src/BlobStorage/Configuration/BlobStorage.cs @@ -1,6 +1,4 @@ -using SenseNet.ContentRepository.Storage; - -// ReSharper disable once CheckNamespace +// ReSharper disable once CheckNamespace namespace SenseNet.Configuration { /// @@ -31,15 +29,6 @@ public class BlobStorage : SnConfig /// public static int BinaryCacheSize { get; internal set; } = GetInt(SectionName, "BinaryCacheSize", 1048576, 102400, 104857600); - /// - /// Minimum size limit (in bytes) for binary data to be stored in a SQL FileStream column. - /// Files smaller or equal this size will be stored in the database. Bigger files will go - /// to a FileStream column if the feature is enabled in the database. - /// If you set this to 0, all files will go to the filestream column. - /// In case of a huge value everything will remain in the db. - /// - public static int MinimumSizeForFileStreamInBytes { get; internal set; } = GetInt(SectionName, "MinimumSizeForFileStreamKB", 500) * 1024; - /// /// Minimum size limit (in bytes) for binary data to be stored in the external blob storage. /// Files under this size will be stored in the database. If you set this to 0, all files @@ -47,15 +36,13 @@ public class BlobStorage : SnConfig /// public static int MinimumSizeForBlobProviderInBytes { get; internal set; } = GetInt(SectionName, "MinimumSizeForBlobProviderKB", 500) * 1024; - /// - /// Whether the FileStream feature is enabled in the system or not. - /// Computed property, not possible to configure. - /// - public static bool FileStreamEnabled { get; internal set; } = BlobStorageComponents.DataProvider.IsFilestreamEnabled(); - /// /// Class name of an optional external blob storage provider. /// public static string BlobProviderClassName { get; internal set; } = GetString(SectionName, "BlobProvider"); + /// + /// Class name of an optional external metadata provider for the blob storage. + /// + public static string MetadataProviderClassName { get; internal set; } = GetString(SectionName, "MetadataProvider"); } } diff --git a/src/BlobStorage/Data/BlobStorageBase.cs b/src/BlobStorage/Data/BlobStorageBase.cs index 9538f9bd8..26695361b 100644 --- a/src/BlobStorage/Data/BlobStorageBase.cs +++ b/src/BlobStorage/Data/BlobStorageBase.cs @@ -58,7 +58,7 @@ protected internal static void DeleteBinaryProperty(int versionId, int propertyT /// Whether the blob provider should clear the stream during assembling the context. /// Content version id. /// Binary property type id. - protected internal static BlobStorageContext GetBlobStorageContext(int fileId, bool clearStream = false, int versionId = 0, int propertyTypeId = 0) + public static BlobStorageContext GetBlobStorageContext(int fileId, bool clearStream = false, int versionId = 0, int propertyTypeId = 0) { return BlobStorageComponents.DataProvider.GetBlobStorageContext(fileId, clearStream, versionId, propertyTypeId); } @@ -150,7 +150,7 @@ protected internal static void WriteChunk(int versionId, string token, byte[] bu } catch (Exception ex) { - throw new DataException("Error during saving binary chunk to filestream.", ex); + throw new DataException("Error during saving binary chunk to stream.", ex); } } } @@ -181,7 +181,7 @@ protected internal static async Task WriteChunkAsync(int versionId, string token } catch (Exception ex) { - throw new DataException("Error during saving binary chunk to filestream.", ex); + throw new DataException("Error during saving binary chunk to stream.", ex); } } } @@ -222,7 +222,7 @@ protected internal static void CopyFromStream(int versionId, string token, Strea { var context = GetBlobStorageContext(tokenData.FileId, true, versionId, tokenData.PropertyTypeId); - if (context.Provider == BuiltInProvider && !UseFileStream(context.Length)) + if (context.Provider == BuiltInProvider) { // Our built-in provider does not have a special stream for the case when // the binary should be saved into a regular SQL varbinary column. @@ -240,7 +240,7 @@ protected internal static void CopyFromStream(int versionId, string token, Strea } catch (Exception e) { - throw new DataException("Error during saving binary chunk to filestream.", e); + throw new DataException("Error during saving binary chunk to stream.", e); } } /// @@ -259,7 +259,7 @@ protected internal static async Task CopyFromStreamAsync(int versionId, string t { var context = await GetBlobStorageContextAsync(tokenData.FileId, true, versionId, tokenData.PropertyTypeId); - if (context.Provider == BuiltInProvider && !UseFileStream(context.Length)) + if (context.Provider == BuiltInProvider) { // Our built-in provider does not have a special stream for the case when // the binary should be saved into a regular SQL varbinary column. @@ -277,7 +277,7 @@ protected internal static async Task CopyFromStreamAsync(int versionId, string t } catch (Exception e) { - throw new DataException("Error during saving binary chunk to filestream.", e); + throw new DataException("Error during saving binary chunk to stream.", e); } } private static void CopyFromStreamByChunks(BlobStorageContext context, Stream input) @@ -350,7 +350,7 @@ protected internal static bool CleanupFiles() /// /// Gets an instance of the built-in provider. /// - protected internal static IBlobProvider BuiltInProvider { get; } + public static IBlobProvider BuiltInProvider { get; } /// /// Gets a list of available blob storage providers in the system. /// @@ -373,14 +373,14 @@ static BlobStorageBase() /// Gets a provider based on the binary size and the available blob providers in the system. /// /// Full binary length. - protected internal static IBlobProvider GetProvider(long fullSize) + public static IBlobProvider GetProvider(long fullSize) { return BlobStorageComponents.ProviderSelector.GetProvider(fullSize, Providers, BuiltInProvider); } /// /// Gets the blob provider instance with the specified name. Default is the built-in provider. /// - protected internal static IBlobProvider GetProvider(string providerName) + public static IBlobProvider GetProvider(string providerName) { if (providerName == null) return BuiltInProvider; @@ -389,12 +389,5 @@ protected internal static IBlobProvider GetProvider(string providerName) return provider; throw new InvalidOperationException("BlobProvider not found: '" + providerName + "'."); } - /// - /// Decides whether a binary with the provided length should go to a Filestream column or not. - /// - protected internal static bool UseFileStream(long fullSize) - { - return BlobStorage.FileStreamEnabled && fullSize > BlobStorage.MinimumSizeForFileStreamInBytes; - } } } diff --git a/src/BlobStorage/Data/BlobStorageClient.cs b/src/BlobStorage/Data/BlobStorageClient.cs index a5e22698a..29b0e068e 100644 --- a/src/BlobStorage/Data/BlobStorageClient.cs +++ b/src/BlobStorage/Data/BlobStorageClient.cs @@ -61,7 +61,7 @@ public class BlobStorageClient : BlobStorageBase public static Stream GetStreamForRead(string token) { var tokenData = ChunkToken.Parse(token); - var context = BlobStorageBase.GetBlobStorageContext(tokenData.FileId, false, tokenData.VersionId, tokenData.PropertyTypeId); + var context = GetBlobStorageContext(tokenData.FileId, false, tokenData.VersionId, tokenData.PropertyTypeId); return context.Provider.GetStreamForRead(context); } diff --git a/src/BlobStorage/Data/BlobStorageContext.cs b/src/BlobStorage/Data/BlobStorageContext.cs index 10ca93302..0e7aff2b0 100644 --- a/src/BlobStorage/Data/BlobStorageContext.cs +++ b/src/BlobStorage/Data/BlobStorageContext.cs @@ -37,11 +37,6 @@ public class BlobStorageContext /// public object BlobProviderData { get; set; } - /// - /// Gets a value indicating whether this binary value is (or will be) saved into a Filestream column in SQL Server. - /// - public bool UseFileStream { get; set; } - /// /// Creates a new instance of the BlobStorageContext class. /// @@ -49,7 +44,7 @@ public class BlobStorageContext /// Optional existing provider-specific data in text format. public BlobStorageContext(IBlobProvider provider, string providerData = null) { - this.Provider = provider; + Provider = provider; if (providerData != null) BlobProviderData = provider.ParseData(providerData); } diff --git a/src/BlobStorage/Data/ChunkToken.cs b/src/BlobStorage/Data/ChunkToken.cs index 0e40033bd..749910bfe 100644 --- a/src/BlobStorage/Data/ChunkToken.cs +++ b/src/BlobStorage/Data/ChunkToken.cs @@ -33,9 +33,9 @@ public class ChunkToken /// any time. Only the Parse method below can be used to extract the values. The layers above should /// NOT parse and use the ids compiled into this token. /// - internal string GetToken() + public string GetToken() { - return $"{this.VersionId}|{this.PropertyTypeId}|{this.BinaryPropertyId}|{this.FileId}"; + return $"{VersionId}|{PropertyTypeId}|{BinaryPropertyId}|{FileId}"; } /// diff --git a/src/BlobStorage/Data/FileStreamData.cs b/src/BlobStorage/Data/FileStreamData.cs deleted file mode 100644 index 8e85840cb..000000000 --- a/src/BlobStorage/Data/FileStreamData.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace SenseNet.ContentRepository.Storage.Data -{ - /// - /// Holds context information for SqlFileStream operations. - /// - internal class FileStreamData - { - public string Path { get; set; } - public byte[] TransactionContext { get; set; } - } -} diff --git a/src/BlobStorage/Data/IBlobStorageMetaDataProvider.cs b/src/BlobStorage/Data/IBlobStorageMetaDataProvider.cs index 06352e2db..61114f70a 100644 --- a/src/BlobStorage/Data/IBlobStorageMetaDataProvider.cs +++ b/src/BlobStorage/Data/IBlobStorageMetaDataProvider.cs @@ -11,11 +11,6 @@ namespace SenseNet.ContentRepository.Storage.Data /// public interface IBlobStorageMetaDataProvider { - /// - /// Returns whether the FileStream feature is enabled in the blob provider or not. - /// - bool IsFilestreamEnabled(); - /// /// Returns a context object that holds provider-specific data for blob storage operations. /// diff --git a/src/BlobStorage/Data/RepositoryStream.cs b/src/BlobStorage/Data/RepositoryStream.cs index 1fd1b0319..21e6363f3 100644 --- a/src/BlobStorage/Data/RepositoryStream.cs +++ b/src/BlobStorage/Data/RepositoryStream.cs @@ -67,7 +67,7 @@ public class RepositoryStream : Stream public RepositoryStream(int fileId, long size, byte[] binary = null) { Length = size; - this.FileId = fileId; + FileId = fileId; if (binary != null) _innerBuffer = binary; } diff --git a/src/BlobStorage/Data/SenseNetSqlFileStream.cs b/src/BlobStorage/Data/SenseNetSqlFileStream.cs deleted file mode 100644 index 741b8ed69..000000000 --- a/src/BlobStorage/Data/SenseNetSqlFileStream.cs +++ /dev/null @@ -1,226 +0,0 @@ -using System; -using System.Data.SqlTypes; -using System.IO; -using SenseNet.Configuration; - -#pragma warning disable 1591 - -namespace SenseNet.ContentRepository.Storage.Data -{ - /// - /// Wrapper class for an SqlFilestream. Handles buffered reading - /// and writing of a file stream, including opening and closing - /// a transaction if no open transaction exists. - /// - public class SenseNetSqlFileStream : Stream - { - // ========================================================= Properties - - public override bool CanRead => true; - public override bool CanSeek => true; - public override bool CanWrite => false; - - public override long Position { get; set; } - - public override long Length { get; } - - private byte[] _innerBuffer; - private long _innerBufferFirstPostion; - - public int FileId { get; set; } - - private FileStreamData FileStreamData; - - // ========================================================= Constructor - - internal SenseNetSqlFileStream(long size, int fileId, FileStreamData fileStreamData = null) - { - Length = size; - FileStreamData = fileStreamData?.TransactionContext != null ? fileStreamData : null; - - FileId = fileId; - } - - // ========================================================= Overrided mthods - - public override void SetLength(long value) - { - throw new NotSupportedException("SenseNetSqlFileStream does not support setting length."); - } - - public override void Write(byte[] buffer, int offset, int count) - { - throw new NotSupportedException("SenseNetSqlFileStream does not support writing."); - } - - public override void Flush() - { - throw new NotSupportedException("SenseNetSqlFileStream does not support flushing."); - } - - public override long Seek(long offset, SeekOrigin origin) - { - switch (origin) - { - case SeekOrigin.Begin: - Position = offset; - break; - case SeekOrigin.Current: - Position = Position + offset; - break; - case SeekOrigin.End: - Position = Length - offset; - break; - default: - throw new NotSupportedException(string.Concat("SeekOrigin type ", origin, " is not supported.")); - } - return Position; - } - - public override int Read(byte[] buffer, int offset, int count) - { - if (buffer == null) - throw new ArgumentNullException(nameof(buffer)); - if (offset + count > buffer.Length) - throw new ArgumentException("Offset + count must not be greater than the buffer length."); - if (offset < 0) - throw new ArgumentOutOfRangeException(nameof(offset), "The offset must be greater than zero."); - if (count < 0) - throw new ArgumentOutOfRangeException(nameof(count), "The count must be greater than zero."); - - // Calculate the maximum count of the bytes that can be read. - // Return immediately if nothing to read. - var maximumReadableByteCount = Length - Position; - if (maximumReadableByteCount < 1) - return 0; - - var isLocalTransaction = false; - var realCount = (int)Math.Min(count, maximumReadableByteCount); - - if (CanInnerBufferHandleReadRequest(realCount)) - { - Array.Copy(_innerBuffer, Position - _innerBufferFirstPostion, buffer, offset, realCount); - } - else - { - if (!TransactionScope.IsActive) - { - // make sure we do not use an obsolete value - FileStreamData = null; - - // Start a new transaction here to serve the needs of the SqlFileStream type. - TransactionScope.Begin(); - isLocalTransaction = true; - } - - try - { - // Load transaction data for SqlFilestream. If this is not a local transaction, - // than we will be able to use this data in the future if the client calls - // the Read method multiple times and will not have to execute SQL queries - // every time. - var ctx = BlobStorageBase.GetBlobStorageContext(this.FileId); - if (ctx != null) - if (ctx.Provider == BlobStorageBase.BuiltInProvider) - FileStreamData = ((SqlClient.BuiltinBlobProviderData)ctx.BlobProviderData).FileStreamData; - if (FileStreamData == null) - throw new InvalidOperationException("Transaction data and file path could not be retrieved for SqlFilestream"); - - using (var fs = new SqlFileStream(FileStreamData.Path, FileStreamData.TransactionContext, FileAccess.Read, FileOptions.SequentialScan, 0)) - { - fs.Seek(Position, SeekOrigin.Begin); - - _innerBuffer = null; - - var bytesRead = 0; - var bytesStoredInInnerBuffer = 0; - - while (bytesRead < realCount) - { - var bytesToReadInThisIteration = (int)Math.Min(this.Length - Position - bytesRead, BlobStorage.BinaryChunkSize); - var bytesToStoreInThisIteration = Math.Min(bytesToReadInThisIteration, realCount - bytesRead); - var tempBuffer = new byte[bytesToReadInThisIteration]; - - // copy the bytes from the file stream to the temp buffer - // (it is possible that we loaded a lot more bytes than the client requested) - fs.Read(tempBuffer, 0, bytesToReadInThisIteration); - - // first iteration: create inner buffer for caching a part of the stream in memory - if (_innerBuffer == null) - { - _innerBuffer = new byte[GetInnerBufferSize(realCount)]; - _innerBufferFirstPostion = Position; - } - - // store a fragment of the data in the inner buffer if possible - if (bytesStoredInInnerBuffer < _innerBuffer.Length) - { - var bytesToStoreInInnerBuffer = Math.Min(bytesToReadInThisIteration, _innerBuffer.Length - bytesStoredInInnerBuffer); - - Array.Copy(tempBuffer, 0, _innerBuffer, bytesStoredInInnerBuffer, bytesToStoreInInnerBuffer); - bytesStoredInInnerBuffer += bytesToStoreInInnerBuffer; - } - - // copy the chunk from the temp buffer to the buffer of the caller - Array.Copy(tempBuffer, 0, buffer, bytesRead, bytesToStoreInThisIteration); - bytesRead += bytesToReadInThisIteration; - } - } - } - catch - { - // ReSharper disable once InvertIf - if (isLocalTransaction && TransactionScope.IsActive) - { - TransactionScope.Rollback(); - - // cleanup - isLocalTransaction = false; - FileStreamData = null; - } - throw; - } - finally - { - if (isLocalTransaction && TransactionScope.IsActive) - { - TransactionScope.Commit(); - - // Set filestream data to null as this was a local transaction and we cannot use it anymore - FileStreamData = null; - } - } - } - - Position += realCount; - - return realCount; - } - - // ========================================================= Helper methods - - private bool CanInnerBufferHandleReadRequest(int count) - { - if (_innerBuffer == null) - return false; - - if (Position < _innerBufferFirstPostion) - return false; - - // ReSharper disable once ConvertIfStatementToReturnStatement - if (_innerBufferFirstPostion + _innerBuffer.Length < Position + count) - return false; - - return true; - } - - private static int GetInnerBufferSize(int realCount) - { - // Determine the inner buffer size. It should not be bigger - // than all the data that will be loaded in this Read method call. - return realCount <= BlobStorage.BinaryChunkSize - ? Math.Min(BlobStorage.BinaryChunkSize, BlobStorage.BinaryBufferSize) - : Math.Min((realCount / BlobStorage.BinaryChunkSize + 1) * BlobStorage.BinaryChunkSize, BlobStorage.BinaryBufferSize); - } - } -} diff --git a/src/BlobStorage/Data/SnStream.cs b/src/BlobStorage/Data/SnStream.cs index f87f23e97..7b6b7f0f9 100644 --- a/src/BlobStorage/Data/SnStream.cs +++ b/src/BlobStorage/Data/SnStream.cs @@ -1,6 +1,5 @@ using System; using System.IO; -using System.Runtime.Remoting; using System.Threading; using System.Threading.Tasks; #pragma warning disable 1591 @@ -121,10 +120,6 @@ public override Task FlushAsync(CancellationToken cancellationToken) { return _underlyingStream.FlushAsync(cancellationToken); } - public override ObjRef CreateObjRef(Type requestedType) - { - return _underlyingStream.CreateObjRef(requestedType); - } public override bool Equals(object obj) { return _underlyingStream.Equals(obj); diff --git a/src/BlobStorage/Data/SqlClient/BuiltInBlobProvider.cs b/src/BlobStorage/Data/SqlClient/BuiltInBlobProvider.cs index f00632c25..c7ffc78c1 100644 --- a/src/BlobStorage/Data/SqlClient/BuiltInBlobProvider.cs +++ b/src/BlobStorage/Data/SqlClient/BuiltInBlobProvider.cs @@ -1,47 +1,41 @@ using System; using System.Data; -using System.Data.SqlTypes; using System.IO; using System.Threading.Tasks; -using SenseNet.Configuration; namespace SenseNet.ContentRepository.Storage.Data.SqlClient { /// /// The built-in provider is responsible for saving bytes directly - /// to the Files table (varbinary or SQL filestream column). This + /// to the Files table (varbinary column). This /// provider cannot be removed or replaced by an external provider. /// - internal class BuiltInBlobProvider : IBlobProvider + public class BuiltInBlobProvider : IBlobProvider { + /// public object ParseData(string providerData) { return BlobStorageContext.DeserializeBlobProviderData(providerData); } + /// + /// Throws NotSupportedException. Our algorithms do not use this methon of this type. + /// public void Allocate(BlobStorageContext context) { // Never used in our algorithms. throw new NotSupportedException(); } - internal static void AddStream(BlobStorageContext context, Stream stream) + /// + /// DO NOT USE DIRECTLY THIS METHOD FROM YOUR CODE. + /// Writes the stream in the appropriate row of the Files table specified by the context. + /// + public static void AddStream(BlobStorageContext context, Stream stream) { - FileStreamData fileStreamData = null; - var providerData = context.BlobProviderData as BuiltinBlobProviderData; - if (providerData != null) - fileStreamData = providerData.FileStreamData; - SqlProcedure cmd = null; try { - // if possible, write the stream using the special Filestream technology - if (BlobStorageBase.UseFileStream(stream.Length)) - { - WriteSqlFileStream(stream, context.FileId, fileStreamData); - return; - } - // We have to work with an integer since SQL does not support // binary values bigger than [Int32.MaxValue]. var streamSize = Convert.ToInt32(stream.Length); @@ -52,19 +46,12 @@ internal static void AddStream(BlobStorageContext context, Stream stream) var offsetParameter = cmd.Parameters.Add("@Offset", SqlDbType.Int); var valueParameter = cmd.Parameters.Add("@Value", SqlDbType.VarBinary, streamSize); - if (BlobStorage.FileStreamEnabled) - { - var useFileStreamParameter = cmd.Parameters.Add("@UseFileStream", SqlDbType.TinyInt); - useFileStreamParameter.Value = false; - } - var offset = 0; byte[] buffer = null; stream.Seek(0, SeekOrigin.Begin); // The 'while' loop is misleading here, because we write the whole - // stream at once. Bigger files should go to the Filestream - // column anyway. + // stream at once. Bigger files should go to another blob provider. while (offset < streamSize) { // Buffer size may be less at the end os the stream than the limit @@ -90,69 +77,18 @@ internal static void AddStream(BlobStorageContext context, Stream stream) cmd?.Dispose(); } } - #region UpdateBinaryPropertyFileStreamScript - private const string UpdateBinaryPropertyFileStreamScript = @"UPDATE Files SET Stream = NULL WHERE FileId = @Id; - SELECT FileStream.PathName(), GET_FILESTREAM_TRANSACTION_CONTEXT() - FROM Files WHERE [FileId] = @Id -"; - #endregion - private static void WriteSqlFileStream(Stream stream, int fileId, FileStreamData fileStreamData = null) - { - SqlProcedure cmd = null; - - try - { - // if we did not receive a path and transaction context, retrieve it now from the database - if (fileStreamData == null) - { - cmd = new SqlProcedure { CommandText = UpdateBinaryPropertyFileStreamScript, CommandType = CommandType.Text }; - cmd.Parameters.Add("@Id", SqlDbType.Int).Value = fileId; - - string path; - byte[] transactionContext; - - // Set Stream column to NULL and retrieve file path and - // transaction context for the Filestream column. - using (var reader = cmd.ExecuteReader()) - { - reader.Read(); - - path = reader.GetString(0); - transactionContext = reader.GetSqlBytes(1).Buffer; - } - - fileStreamData = new FileStreamData { Path = path, TransactionContext = transactionContext }; - } - stream.Seek(0, SeekOrigin.Begin); - - using (var fs = new SqlFileStream(fileStreamData.Path, fileStreamData.TransactionContext, FileAccess.Write)) - { - // default buffer size is 4096 - stream.CopyTo(fs); - } - } - finally - { - cmd?.Dispose(); - } - } - - internal static void UpdateStream(BlobStorageContext context, Stream stream) + /// + /// DO NOT USE DIRECTLY THIS METHOD FROM YOUR CODE. + /// Updates the stream in the appropriate row of the Files table specified by the context. + /// + public static void UpdateStream(BlobStorageContext context, Stream stream) { var fileId = context.FileId; - var fileStreamData = ((BuiltinBlobProviderData)context.BlobProviderData).FileStreamData; SqlProcedure cmd = null; try { - // if possible, write the stream using the special Filestream technology - if (BlobStorageBase.UseFileStream(stream.Length)) - { - WriteSqlFileStream(stream, fileId, fileStreamData); - return; - } - // We have to work with an integer since SQL does not support // binary values bigger than [Int32.MaxValue]. var streamSize = Convert.ToInt32(stream.Length); @@ -163,19 +99,12 @@ internal static void UpdateStream(BlobStorageContext context, Stream stream) var offsetParameter = cmd.Parameters.Add("@Offset", SqlDbType.Int); var valueParameter = cmd.Parameters.Add("@Value", SqlDbType.VarBinary, streamSize); - if (BlobStorage.FileStreamEnabled) - { - var useFileStreamParameter = cmd.Parameters.Add("@UseFileStream", SqlDbType.TinyInt); - useFileStreamParameter.Value = false; - } - var offset = 0; byte[] buffer = null; stream.Seek(0, SeekOrigin.Begin); // The 'while' loop is misleading here, because we write the whole - // stream at once. Bigger files should go to the Filestream - // column anyway. + // stream at once. Bigger files should go to another blob provider. while (offset < streamSize) { // Buffer size may be less at the end os the stream than the limit @@ -202,15 +131,13 @@ internal static void UpdateStream(BlobStorageContext context, Stream stream) } } + /// public Stream GetStreamForRead(BlobStorageContext context) { - var data = (BuiltinBlobProviderData)context.BlobProviderData; - if (context.UseFileStream) - return new SenseNetSqlFileStream(context.Length, context.FileId, data.FileStreamData); return new RepositoryStream(context.FileId, context.Length); - } + /// public Stream CloneStream(BlobStorageContext context, Stream stream) { if (stream == null) @@ -220,36 +147,22 @@ public Stream CloneStream(BlobStorageContext context, Stream stream) if (repoStream != null) return new RepositoryStream(repoStream.FileId, repoStream.Length); - var snFileStream = stream as SenseNetSqlFileStream; - if (snFileStream != null) - return new SenseNetSqlFileStream(snFileStream.Length, snFileStream.FileId); - throw new InvalidOperationException("Unknown stream type: " + stream.GetType().Name); } + /// public void Delete(BlobStorageContext context) { // do nothing } - #region LoadBinaryFragmentScript, LoadBinaryFragmentFilestreamScript + #region LoadBinaryFragmentScript private const string LoadBinaryFragmentScript = @"SELECT SUBSTRING([Stream], @Position, @Count) FROM dbo.Files WHERE FileId = @FileId"; - - private const string LoadBinaryFragmentFilestreamScript = @"SELECT - CASE WHEN FileStream IS NULL - THEN SUBSTRING([Stream], @Position, @Count) - ELSE SUBSTRING([FileStream], @Position, @Count) - END AS Stream - FROM dbo.Files - WHERE FileId = @FileId"; - #endregion internal static byte[] ReadRandom(BlobStorageContext context, long offset, int count) { - var commandText = BlobStorage.FileStreamEnabled - ? LoadBinaryFragmentFilestreamScript - : LoadBinaryFragmentScript; + var commandText = LoadBinaryFragmentScript; byte[] result; @@ -266,75 +179,26 @@ internal static byte[] ReadRandom(BlobStorageContext context, long offset, int c return result; } + /// public void Write(BlobStorageContext context, long offset, byte[] buffer) { - if (BlobStorageBase.UseFileStream(context.Length)) - WriteChunkToFilestream(context, offset, buffer); - else - WriteChunkToSql(context, offset, buffer); - } - public async Task WriteAsync(BlobStorageContext context, long offset, byte[] buffer) - { - if (BlobStorageBase.UseFileStream(context.Length)) - await WriteChunkToFilestreamAsync(context, offset, buffer); - else - await WriteChunkToSqlAsync(context, offset, buffer); - } - private static void WriteChunkToFilestream(BlobStorageContext context, long offset, byte[] buffer) - { - using (var fs = GetAndExtendFileStream(context, offset)) - { - // no offset is needed here, the stream is already at the correct position - fs.Write(buffer, 0, buffer.Length); - } - } - private static async Task WriteChunkToFilestreamAsync(BlobStorageContext context, long offset, byte[] buffer) - { - using (var fs = GetAndExtendFileStream(context, offset)) + using (var cmd = GetWriteChunkToSqlProcedure(context, offset, buffer)) { - // no offset is needed here, the stream is already at the correct position - await fs.WriteAsync(buffer, 0, buffer.Length); + cmd.ExecuteNonQuery(); } } - /// - /// Loads a SqlFileStream object for the binary in the provided context and sets it to the required position. - /// If the filestream is shorter than the required offset, it extends the stream with empty bytes. - /// - private static SqlFileStream GetAndExtendFileStream(BlobStorageContext context, long offset) + /// + public async Task WriteAsync(BlobStorageContext context, long offset, byte[] buffer) { - var fsd = ((BuiltinBlobProviderData)context.BlobProviderData).FileStreamData; - if (fsd == null) - throw new InvalidOperationException("File row not found. FileId: " + context.FileId); - - var fs = new SqlFileStream(fsd.Path, fsd.TransactionContext, FileAccess.ReadWrite, FileOptions.SequentialScan, 0); - - // if the current stream is smaller than the position where we want to write the bytes - if (fs.Length < offset) - { - // go to the end of the existing stream - fs.Seek(0, SeekOrigin.End); - - // calculate the size of the gap (warning: fs.Length changes during the write below!) - var gapSize = offset - fs.Length; - - // fill the gap with empty bytes (one-by-one, because this gap could be huge) - for (var i = 0; i < gapSize; i++) - { - fs.WriteByte(0x00); - } - } - else if (offset > 0) + using (var cmd = GetWriteChunkToSqlProcedure(context, offset, buffer)) { - // otherwise we will append to the end or overwrite existing bytes - fs.Seek(offset, SeekOrigin.Begin); + await cmd.ExecuteNonQueryAsync(); } - - return fs; } - #region UpdateStreamWriteChunkTemplateScript, UpdateStreamWriteChunkScript, UpdateStreamWriteChunkFsScript - private static readonly string UpdateStreamWriteChunkTemplateScript = MsSqlBlobMetaDataProvider.UpdateStreamWriteChunkSecurityCheckScript + @" + #region UpdateStreamWriteChunkScript + private static readonly string UpdateStreamWriteChunkScript = MsSqlBlobMetaDataProvider.UpdateStreamWriteChunkSecurityCheckScript + @" -- init for .WRITE UPDATE Files SET [Stream] = (CONVERT(varbinary, N'')) WHERE FileId = @FileId AND [Stream] IS NULL -- fill to offset @@ -344,38 +208,15 @@ IF @StreamLength < @Offset UPDATE Files SET [Stream].WRITE(CONVERT( varbinary, REPLICATE(0x00, (@Offset - DATALENGTH([Stream])))), NULL, 0) WHERE FileId = @FileId -- write payload -UPDATE Files SET [Stream].WRITE(@Data, @Offset, DATALENGTH(@Data)){0} WHERE FileId = @FileId"; - - private static readonly string UpdateStreamWriteChunkScript = string.Format(UpdateStreamWriteChunkTemplateScript, string.Empty); - private static readonly string UpdateStreamWriteChunkFsScript = string.Format(UpdateStreamWriteChunkTemplateScript, ", [FileStream] = NULL"); +UPDATE Files SET [Stream].WRITE(@Data, @Offset, DATALENGTH(@Data)) WHERE FileId = @FileId"; #endregion - private static void WriteChunkToSql(BlobStorageContext context, long offset, byte[] buffer) - { - using (var cmd = GetWriteChunkToSqlProcedure(context, offset, buffer)) - { - cmd.ExecuteNonQuery(); - } - } - private static async Task WriteChunkToSqlAsync(BlobStorageContext context, long offset, byte[] buffer) - { - using (var cmd = GetWriteChunkToSqlProcedure(context, offset, buffer)) - { - await cmd.ExecuteNonQueryAsync(); - } - } // ReSharper disable once SuggestBaseTypeForParameter private static SqlProcedure GetWriteChunkToSqlProcedure(BlobStorageContext context, long offset, byte[] buffer) { // This is a helper method to aid both the sync and async version of the write chunk operation. - // If Filestream is enabled but not used, we need to set it NULL - // when inserting the chunk to the regular Stream column - var cmdText = BlobStorage.FileStreamEnabled - ? UpdateStreamWriteChunkFsScript - : UpdateStreamWriteChunkScript; - - var cmd = new SqlProcedure { CommandText = cmdText, CommandType = CommandType.Text }; + var cmd = new SqlProcedure { CommandText = UpdateStreamWriteChunkScript, CommandType = CommandType.Text }; cmd.Parameters.Add("@FileId", SqlDbType.Int).Value = context.FileId; cmd.Parameters.Add("@VersionId", SqlDbType.Int).Value = context.VersionId; @@ -386,17 +227,12 @@ private static SqlProcedure GetWriteChunkToSqlProcedure(BlobStorageContext conte return cmd; } + /// + /// Throws NotSupportedException. Our algorithms do not use this methon of this type. + /// public Stream GetStreamForWrite(BlobStorageContext context) { - if (!BlobStorageBase.UseFileStream(context.Length)) - throw new NotSupportedException(); - - var fsd = ((BuiltinBlobProviderData)context.BlobProviderData).FileStreamData; - if (fsd == null) - throw new InvalidOperationException("File row not found. FileId: " + context.FileId); - - return new SqlFileStream(fsd.Path, fsd.TransactionContext, FileAccess.ReadWrite, - FileOptions.SequentialScan, 0); + throw new NotSupportedException(); } } } diff --git a/src/BlobStorage/Data/SqlClient/BuiltInBlobProviderSelector.cs b/src/BlobStorage/Data/SqlClient/BuiltInBlobProviderSelector.cs index f58d8f733..b90647e4d 100644 --- a/src/BlobStorage/Data/SqlClient/BuiltInBlobProviderSelector.cs +++ b/src/BlobStorage/Data/SqlClient/BuiltInBlobProviderSelector.cs @@ -20,9 +20,12 @@ public class BuiltInBlobProviderSelector : IBlobProviderSelector /// /// A custom blob provider instance that can be configured in the section. /// - protected static IBlobProvider ExternalBlobProvider { get; set; } + protected internal static IBlobProvider ExternalBlobProvider { get; set; } - static BuiltInBlobProviderSelector() + /// + /// Initializes an instance of the BuiltInBlobProviderSelector + /// + public BuiltInBlobProviderSelector() { // check if there is a configuration for an external blob provider if (string.IsNullOrEmpty(BlobStorage.BlobProviderClassName)) diff --git a/src/BlobStorage/Data/SqlClient/BuiltinBlobProviderData.cs b/src/BlobStorage/Data/SqlClient/BuiltinBlobProviderData.cs index 5b2f9c56f..746187db7 100644 --- a/src/BlobStorage/Data/SqlClient/BuiltinBlobProviderData.cs +++ b/src/BlobStorage/Data/SqlClient/BuiltinBlobProviderData.cs @@ -3,12 +3,7 @@ /// /// Blob provider data for the built-in blob provider. /// - internal class BuiltinBlobProviderData + public class BuiltinBlobProviderData { - /// - /// Custom data for the Filestream column. - /// - [Newtonsoft.Json.JsonProperty("FileStreamData")] - public FileStreamData FileStreamData { get; set; } } } diff --git a/src/BlobStorage/Data/SqlClient/MsSqlBlobMetaDataProvider.cs b/src/BlobStorage/Data/SqlClient/MsSqlBlobMetaDataProvider.cs index be248f1d2..ee62b90d1 100644 --- a/src/BlobStorage/Data/SqlClient/MsSqlBlobMetaDataProvider.cs +++ b/src/BlobStorage/Data/SqlClient/MsSqlBlobMetaDataProvider.cs @@ -4,7 +4,6 @@ using System.IO; using System.Threading.Tasks; using SenseNet.Configuration; -using SenseNet.Diagnostics; using SenseNet.Tools; namespace SenseNet.ContentRepository.Storage.Data.SqlClient @@ -22,49 +21,18 @@ private static string ValidateExtension(string originalExtension) : string.Concat(".", originalExtension); } - /// - /// Returns whether the FileStream feature is enabled in the blob provider or not. - /// - /// - public bool IsFilestreamEnabled() - { - bool fsEnabled; - const string sql = "SELECT COUNT(name) FROM sys.columns WHERE Name = N'FileStream' and Object_ID = Object_ID(N'Files')"; - using (var pro = new SqlProcedure {CommandText = sql, CommandType=CommandType.Text}) - { - try - { - fsEnabled = Convert.ToInt32(pro.ExecuteScalar()) > 0; - } - catch (Exception ex) - { - SnLog.WriteException(ex); - fsEnabled = false; - } - } - return fsEnabled; - } - - #region ClearStreamByFileIdScript, ClearFileStreamByFileIdScript, GetBlobContextDataScript, GetBlobContextDataFileStreamScript - - private const string GetBlobContextDataFileStreamScript = @" SELECT Size, BlobProvider, BlobProviderData, FileStream.PathName() AS Path, GET_FILESTREAM_TRANSACTION_CONTEXT() AS TransactionContext -FROM dbo.Files WHERE FileId = @FileId -"; + #region ClearStreamByFileIdScript, GetBlobContextDataScript private const string GetBlobContextDataScript = @" SELECT Size, BlobProvider, BlobProviderData FROM dbo.Files WHERE FileId = @FileId "; - - private const string ClearFileStreamByFileIdScript = @"UPDATE Files SET Stream = NULL, FileStream = CONVERT(varbinary, N'') WHERE FileId = @FileId AND FileStream IS NULL; -"; - private const string ClearStreamByFileIdScript = @"UPDATE Files SET Stream = NULL WHERE FileId = @FileId; "; #endregion /// - /// Returns a context object that holds MsSql-specific data (e.g. FileStream info) for blob storage operations. + /// Returns a context object that holds MsSql-specific data for blob storage operations. /// /// File identifier. /// Whether the blob provider should clear the stream during assembling the context. @@ -73,20 +41,13 @@ public bool IsFilestreamEnabled() public BlobStorageContext GetBlobStorageContext(int fileId, bool clearStream, int versionId, int propertyTypeId) { using (var cmd = GetBlobContextProcedure(fileId, clearStream, versionId, propertyTypeId)) - { - using (var reader = cmd.ExecuteReader(CommandBehavior.SingleRow | CommandBehavior.SingleResult)) - { - if (reader.Read()) - { - return GetBlobStorageContextPrivate(reader, fileId, versionId, propertyTypeId); - } - - return null; - } - } + using (var reader = cmd.ExecuteReader(CommandBehavior.SingleRow | CommandBehavior.SingleResult)) + if (reader.Read()) + return GetBlobStorageContextPrivate(reader, fileId, versionId, propertyTypeId); + return null; } /// - /// Returns a context object that holds MsSql-specific data (e.g. FileStream info) for blob storage operations. + /// Returns a context object that holds MsSql-specific data for blob storage operations. /// /// File identifier. /// Whether the blob provider should clear the stream during assembling the context. @@ -95,17 +56,10 @@ public BlobStorageContext GetBlobStorageContext(int fileId, bool clearStream, in public async Task GetBlobStorageContextAsync(int fileId, bool clearStream, int versionId, int propertyTypeId) { using (var cmd = GetBlobContextProcedure(fileId, clearStream, versionId, propertyTypeId)) - { - using (var reader = await cmd.ExecuteReaderAsync(CommandBehavior.SingleRow | CommandBehavior.SingleResult)) - { - if (await reader.ReadAsync()) - { - return GetBlobStorageContextPrivate(reader, fileId, versionId, propertyTypeId); - } - - return null; - } - } + using (var reader = await cmd.ExecuteReaderAsync(CommandBehavior.SingleRow | CommandBehavior.SingleResult)) + if (await reader.ReadAsync()) + return GetBlobStorageContextPrivate(reader, fileId, versionId, propertyTypeId); + return null; } private static SqlProcedure GetBlobContextProcedure(int fileId, bool clearStream, int versionId, int propertyTypeId) @@ -113,15 +67,11 @@ private static SqlProcedure GetBlobContextProcedure(int fileId, bool clearStream // this is a helper method to aid both the sync and // async version of the GetBlobContext operation - var sql = BlobStorage.FileStreamEnabled - ? GetBlobContextDataFileStreamScript - : GetBlobContextDataScript; + var sql = GetBlobContextDataScript; // add clear stream prefix of necessary if (clearStream) - sql = (BlobStorage.FileStreamEnabled - ? ClearFileStreamByFileIdScript - : ClearStreamByFileIdScript) + sql; + sql = ClearStreamByFileIdScript + sql; var cmd = new SqlProcedure {CommandText = sql, CommandType = CommandType.Text}; @@ -145,19 +95,6 @@ private static BlobStorageContext GetBlobStorageContextPrivate(SqlDataReader rea var providerName = reader.GetSafeString(1); var providerData = reader.GetSafeString(2); - var useFileStream = false; - FileStreamData fsData = null; - - if (BlobStorage.FileStreamEnabled) - { - fsData = new FileStreamData - { - Path = reader.GetSafeString(3), - TransactionContext = reader.GetSqlBytes(4).Buffer - }; - useFileStream = fsData.Path != null; - } - var provider = BlobStorageBase.GetProvider(providerName); return new BlobStorageContext(provider, providerData) @@ -166,14 +103,13 @@ private static BlobStorageContext GetBlobStorageContextPrivate(SqlDataReader rea PropertyTypeId = propertyTypeId, FileId = fileId, Length = length, - UseFileStream = useFileStream, BlobProviderData = provider == BlobStorageBase.BuiltInProvider - ? new BuiltinBlobProviderData { FileStreamData = fsData } + ? new BuiltinBlobProviderData() : provider.ParseData(providerData) }; } - #region DeleteBinaryPropertyScript, InsertBinaryPropertyScript, InsertBinaryPropertyFilestreamScript + #region DeleteBinaryPropertyScript, InsertBinaryPropertyScript internal const string DeleteBinaryPropertyScript = @"DELETE BinaryProperties WHERE VersionId = @VersionId AND PropertyTypeId = @PropertyTypeId "; @@ -188,22 +124,9 @@ private static BlobStorageContext GetBlobStorageContextPrivate(SqlDataReader rea DECLARE @BinPropId int; SELECT @BinPropId = @@IDENTITY; SELECT @BinPropId, @FileId, [Timestamp] FROM Files WHERE FileId = @FileId; -"; - - private const string InsertBinaryPropertyFilestreamScript = @"INSERT INTO Files" + -@" (ContentType, FileNameWithoutExtension, Extension, [Size], [BlobProvider], [BlobProviderData], [Checksum], [FileStream]) -VALUES (@ContentType, @FileNameWithoutExtension, @Extension, @Size, @BlobProvider, @BlobProviderData, - CASE @Size WHEN 0 THEN NULL ELSE @Checksum END, CASE @Size WHEN 0 THEN NULL ELSE (0x) END); -DECLARE @FileId int; SELECT @FileId = @@IDENTITY; - -INSERT INTO BinaryProperties (VersionId, PropertyTypeId, FileId) VALUES (@VersionId, @PropertyTypeId, @FileId); -DECLARE @BinPropId int; SELECT @BinPropId = @@IDENTITY; - -SELECT @BinPropId, @FileId, [Timestamp], FileStream.PathName(), GET_FILESTREAM_TRANSACTION_CONTEXT() FROM Files WHERE FileId = @FileId; "; private const string DeleteAndInsertBinaryProperty = DeleteBinaryPropertyScript + InsertBinaryPropertyScript; - private const string DeleteAndInsertBinaryPropertyFilestream = DeleteBinaryPropertyScript + InsertBinaryPropertyFilestreamScript; #endregion /// @@ -218,9 +141,7 @@ private static BlobStorageContext GetBlobStorageContextPrivate(SqlDataReader rea public void InsertBinaryProperty(IBlobProvider blobProvider, BinaryDataValue value, int versionId, int propertyTypeId, bool isNewNode) { var streamLength = value.Stream?.Length ?? 0; - var useFileStream = BlobStorage.FileStreamEnabled && - streamLength > Convert.ToInt64(BlobStorage.MinimumSizeForFileStreamInBytes); - var ctx = new BlobStorageContext(blobProvider) { VersionId = versionId, PropertyTypeId = propertyTypeId, FileId = 0, Length = streamLength, UseFileStream = useFileStream }; + var ctx = new BlobStorageContext(blobProvider) { VersionId = versionId, PropertyTypeId = propertyTypeId, FileId = 0, Length = streamLength }; // In case of an external provider allocate the place for bytes and // write the stream beforehand and get the generated provider data. @@ -238,12 +159,9 @@ public void InsertBinaryProperty(IBlobProvider blobProvider, BinaryDataValue val } SqlProcedure cmd = null; - FileStreamData fileStreamData = null; try { - cmd = useFileStream - ? new SqlProcedure { CommandText = isNewNode ? InsertBinaryPropertyFilestreamScript : DeleteAndInsertBinaryPropertyFilestream, CommandType = CommandType.Text } - : new SqlProcedure { CommandText = isNewNode ? InsertBinaryPropertyScript : DeleteAndInsertBinaryProperty, CommandType = CommandType.Text }; + cmd = new SqlProcedure { CommandText = isNewNode ? InsertBinaryPropertyScript : DeleteAndInsertBinaryProperty, CommandType = CommandType.Text }; cmd.Parameters.Add("@VersionId", SqlDbType.Int).Value = versionId != 0 ? (object)versionId : DBNull.Value; cmd.Parameters.Add("@PropertyTypeId", SqlDbType.Int).Value = propertyTypeId != 0 ? (object)propertyTypeId : DBNull.Value; @@ -255,7 +173,7 @@ public void InsertBinaryProperty(IBlobProvider blobProvider, BinaryDataValue val cmd.Parameters.Add("@BlobProviderData", SqlDbType.NVarChar, int.MaxValue).Value = value.BlobProviderData != null ? (object)value.BlobProviderData : DBNull.Value; cmd.Parameters.Add("@Checksum", SqlDbType.VarChar, 200).Value = value.Checksum != null ? (object)value.Checksum : DBNull.Value; - // insert binary and file rows and retrieve file path and transaction context for the Filestream column + // insert binary and file rows and retrieve new ids. using (var reader = cmd.ExecuteReader()) { reader.Read(); @@ -263,14 +181,6 @@ public void InsertBinaryProperty(IBlobProvider blobProvider, BinaryDataValue val value.Id = Convert.ToInt32(reader[0]); value.FileId = Convert.ToInt32(reader[1]); value.Timestamp = Utility.Convert.BytesToLong((byte[])reader.GetValue(2)); - if (useFileStream) - { - fileStreamData = new FileStreamData - { - Path = reader.GetString(3), - TransactionContext = reader.GetSqlBytes(4).Buffer - }; - } } } @@ -281,13 +191,12 @@ public void InsertBinaryProperty(IBlobProvider blobProvider, BinaryDataValue val // The BuiltIn blob provider saves the stream after the record // was saved into the Files table, because simple varbinary - // and sql filestream columns must exist before we can write a - // stream into the record. + // column must exist before we can write a stream into the record. // ReSharper disable once InvertIf if (blobProvider == BlobStorageBase.BuiltInProvider && value.Stream != null && value.Stream.Length > 0) { ctx.FileId = value.FileId; - ctx.BlobProviderData = new BuiltinBlobProviderData { FileStreamData = fileStreamData }; + ctx.BlobProviderData = new BuiltinBlobProviderData(); BuiltInBlobProvider.AddStream(ctx, value.Stream); } @@ -334,8 +243,8 @@ public void InsertBinaryPropertyWithFileId(BinaryDataValue value, int versionId, value.Id = id; } - #region UpdateBinarypropertyNewFilerowScript, UpdateBinarypropertyNewFilerowFilestreamScript - private const string UpdateBinarypropertyNewFilerowScript = @"DECLARE @FileId int + #region UpdateBinarypropertyNewFilerowScript + private const string UpdateBinaryPropertyNewFilerowScript = @"DECLARE @FileId int INSERT INTO Files (ContentType, FileNameWithoutExtension, Extension, [Size], [BlobProvider], [BlobProviderData], [Checksum], [Stream]) VALUES (@ContentType, @FileNameWithoutExtension, @Extension, @Size, @BlobProvider, @BlobProviderData, CASE WHEN (@Size <= 0) THEN NULL ELSE @Checksum END, @@ -345,15 +254,6 @@ CASE WHEN (@Size <= 0) THEN NULL ELSE CONVERT(varbinary, '') END) SELECT @FileId "; - private const string UpdateBinarypropertyNewFilerowFilestreamScript = @"DECLARE @FileId int -INSERT INTO Files (ContentType, FileNameWithoutExtension, Extension, [Size], [BlobProvider], [BlobProviderData], [Checksum], [Stream], [FileStream]) - VALUES (@ContentType, @FileNameWithoutExtension, @Extension, @Size, @BlobProvider, @BlobProviderData, - CASE WHEN (@Size <= 0) THEN NULL ELSE @Checksum END, - NULL, CASE WHEN (@Size <= 0) THEN NULL ELSE CONVERT(varbinary, '') END) -SELECT @FileId = @@IDENTITY -UPDATE BinaryProperties SET FileId = @FileId WHERE BinaryPropertyId = @BinaryPropertyId -SELECT @FileId, FileStream.PathName(), GET_FILESTREAM_TRANSACTION_CONTEXT() FROM Files WHERE FileId = @FileId -"; #endregion /// @@ -372,7 +272,6 @@ public void UpdateBinaryProperty(IBlobProvider blobProvider, BinaryDataValue val PropertyTypeId = 0, FileId = value.FileId, Length = streamLength, - UseFileStream = false }; blobProvider.Allocate(ctx); @@ -388,21 +287,19 @@ public void UpdateBinaryProperty(IBlobProvider blobProvider, BinaryDataValue val value.BlobProviderData = null; } - if (blobProvider == BlobStorageBase.BuiltInProvider && !BlobStorage.FileStreamEnabled) + if (blobProvider == BlobStorageBase.BuiltInProvider) { - // MS-SQL does not support stream size over [Int32.MaxValue], - // but check only if Filestream is not enabled + // MS-SQL does not support stream size over [Int32.MaxValue]. if (streamLength > int.MaxValue) throw new NotSupportedException(); } - var isRepositoryStream = value.Stream is RepositoryStream || value.Stream is SenseNetSqlFileStream; + var isRepositoryStream = value.Stream is RepositoryStream; var hasStream = isRepositoryStream || value.Stream is MemoryStream; if (!hasStream) // do not do any database operation if the stream is not modified return; - FileStreamData fileStreamData = null; SqlProcedure cmd = null; try { @@ -416,9 +313,7 @@ public void UpdateBinaryProperty(IBlobProvider blobProvider, BinaryDataValue val else { commandType = CommandType.Text; - sql = BlobStorage.FileStreamEnabled - ? UpdateBinarypropertyNewFilerowFilestreamScript - : UpdateBinarypropertyNewFilerowScript; + sql = UpdateBinaryPropertyNewFilerowScript; } cmd = new SqlProcedure { CommandText = sql, CommandType = commandType }; @@ -431,36 +326,13 @@ public void UpdateBinaryProperty(IBlobProvider blobProvider, BinaryDataValue val cmd.Parameters.Add("@BlobProvider", SqlDbType.NVarChar, 450).Value = value.BlobProviderName != null ? (object)value.BlobProviderName : DBNull.Value; cmd.Parameters.Add("@BlobProviderData", SqlDbType.NVarChar, int.MaxValue).Value = value.BlobProviderData != null ? (object)value.BlobProviderData : DBNull.Value; - int fileId; - if (BlobStorage.FileStreamEnabled) - { - string path; - byte[] transactionContext; - - // Update row and retrieve file path and - // transaction context for the Filestream column - using (var reader = cmd.ExecuteReader()) - { - reader.Read(); - - fileId = reader.GetInt32(0); - path = reader.GetSafeString(1); - transactionContext = reader.IsDBNull(2) ? null : reader.GetSqlBytes(2).Buffer; - } - - if (!string.IsNullOrEmpty(path)) - fileStreamData = new FileStreamData { Path = path, TransactionContext = transactionContext }; - } - else - { - fileId = (int)cmd.ExecuteScalar(); - } + var fileId = (int)cmd.ExecuteScalar(); if (fileId > 0 && fileId != value.FileId) value.FileId = fileId; } finally { - cmd?.Dispose(); + cmd.Dispose(); } // ReSharper disable once InvertIf @@ -473,8 +345,7 @@ public void UpdateBinaryProperty(IBlobProvider blobProvider, BinaryDataValue val PropertyTypeId = 0, FileId = value.FileId, Length = streamLength, - UseFileStream = fileStreamData != null, - BlobProviderData = new BuiltinBlobProviderData { FileStreamData = fileStreamData } + BlobProviderData = new BuiltinBlobProviderData() }; BuiltInBlobProvider.UpdateStream(ctx, value.Stream); @@ -502,24 +373,9 @@ public void DeleteBinaryProperty(int versionId, int propertyTypeId) } } - #region LoadBinaryCacheentityColumnsFormatScript, LoadBinaryCacheentityColumnsFormatFilestreamScript, LoadBinaryCacheentityFormatScript - - private const string LoadBinaryCacheentityColumnsFormatScript = @"CASE WHEN F.Size < {0} THEN F.Stream - ELSE null - END AS Stream"; - - private const string LoadBinaryCacheentityColumnsFormatFilestreamScript = @"CASE WHEN Size < {0} AND F.FileStream IS NOT NULL THEN F.FileStream - WHEN Size < {0} AND F.FileStream IS NULL THEN F.Stream - ELSE null - END AS Stream, - CASE - WHEN F.FileStream IS NULL THEN 0 - ELSE 1 - END AS UseFileStream, - F.FileStream.PathName() AS Path, - GET_FILESTREAM_TRANSACTION_CONTEXT() AS TransactionContext"; + #region LoadBinaryCacheentityFormatScript - private const string LoadBinaryCacheentityFormatScript = @"SELECT F.Size, B.BinaryPropertyId, F.FileId, F.BlobProvider, F.BlobProviderData, {0} + private const string LoadBinaryCacheEntityFormatScript = @"SELECT F.Size, B.BinaryPropertyId, F.FileId, F.BlobProvider, F.BlobProviderData, CASE WHEN F.Size < {0} THEN F.Stream ELSE null END AS Stream FROM dbo.BinaryProperties B JOIN Files F ON B.FileId = F.FileId WHERE B.VersionId = @VersionId AND B.PropertyTypeId = @PropertyTypeId AND F.Staging IS NULL"; @@ -534,11 +390,7 @@ FROM dbo.BinaryProperties B /// Binary property type id. public BinaryCacheEntity LoadBinaryCacheEntity(int versionId, int propertyTypeId) { - var columnDefinitions = BlobStorage.FileStreamEnabled - ? string.Format(LoadBinaryCacheentityColumnsFormatFilestreamScript, BlobStorage.BinaryCacheSize) - : string.Format(LoadBinaryCacheentityColumnsFormatScript, BlobStorage.BinaryCacheSize); - - var commandText = string.Format(LoadBinaryCacheentityFormatScript, columnDefinitions); + var commandText = string.Format(LoadBinaryCacheEntityFormatScript, BlobStorage.BinaryCacheSize); using (var cmd = new SqlProcedure { CommandText = commandText }) { @@ -564,28 +416,10 @@ public BinaryCacheEntity LoadBinaryCacheEntity(int versionId, int propertyTypeId else rawData = (byte[])reader.GetValue(5); - var useFileStream = false; - - FileStreamData fileStreamData = null; - if (BlobStorage.FileStreamEnabled) - { - useFileStream = reader.GetInt32(6) == 1; - - if (useFileStream) - { - // fill Filestream info if we really need it - fileStreamData = new FileStreamData - { - Path = reader.GetSafeString(7), - TransactionContext = reader.GetSqlBytes(8).Buffer - }; - } - } - var provider = BlobStorageBase.GetProvider(providerName); - var context = new BlobStorageContext(provider, providerTextData) { VersionId = versionId, PropertyTypeId = propertyTypeId, FileId = fileId, Length = length, UseFileStream = useFileStream }; + var context = new BlobStorageContext(provider, providerTextData) { VersionId = versionId, PropertyTypeId = propertyTypeId, FileId = fileId, Length = length }; if (provider == BlobStorageBase.BuiltInProvider) - context.BlobProviderData = new BuiltinBlobProviderData { FileStreamData = fileStreamData }; + context.BlobProviderData = new BuiltinBlobProviderData(); return new BinaryCacheEntity { @@ -599,9 +433,9 @@ public BinaryCacheEntity LoadBinaryCacheEntity(int versionId, int propertyTypeId } } - #region InsertStagingBinaryStartScript, InsertStagingBinaryScript, InsertStagingBinaryFsScript, InsertStagingBinaryEndScript + #region InsertStagingBinaryScript - private const string InsertStagingBinaryStartScript = @" + private const string InsertStagingBinaryScript = @" DECLARE @ContentType varchar(50); DECLARE @FileNameWithoutExtension varchar(450); DECLARE @Extension varchar(50); @@ -621,16 +455,10 @@ SELECT TOP(1) @ContentType = F.ContentType, @FileNameWithoutExtension = F.FileNa SET @FileNameWithoutExtension = ''; SET @Extension = ''; END -"; - private const string InsertStagingBinaryScript = @" + INSERT INTO Files ([ContentType],[FileNameWithoutExtension],[Extension],[Size],[Checksum],[CreationDate], [Staging], [StagingVersionId], [StagingPropertyTypeId], [BlobProvider], [BlobProviderData]) VALUES (@ContentType, @FileNameWithoutExtension, @Extension, @Size, NULL, GETUTCDATE(), 1, @VersionId, @PropertyTypeId, @BlobProvider, @BlobProviderData); -"; - private const string InsertStagingBinaryFsScript = @" -INSERT INTO Files ([ContentType],[FileNameWithoutExtension],[Extension],[Size],[Checksum],[CreationDate], [Staging], [StagingVersionId], [StagingPropertyTypeId], [BlobProvider], [BlobProviderData], [FileStream]) -VALUES (@ContentType, @FileNameWithoutExtension, @Extension, @Size, NULL, GETUTCDATE(), 1, @VersionId, @PropertyTypeId, @BlobProvider, @BlobProviderData, CASE @UseSqlFileStream WHEN 0 THEN NULL ELSE (0x) END); -"; - private const string InsertStagingBinaryEndScript = @" + SET @FileId = @@IDENTITY; -- lazy binary row creation @@ -663,33 +491,23 @@ public string StartChunk(IBlobProvider blobProvider, int versionId, int property if (isLocalTransaction) TransactionScope.Begin(); - var ctx = new BlobStorageContext(blobProvider) { VersionId = versionId, PropertyTypeId = propertyTypeId, FileId = 0, Length = fullSize, UseFileStream = false }; + var ctx = new BlobStorageContext(blobProvider) { VersionId = versionId, PropertyTypeId = propertyTypeId, FileId = 0, Length = fullSize }; string blobProviderName = null; string blobProviderData = null; - bool useSqlFileStream; - if (blobProvider == BlobStorageBase.BuiltInProvider) - { - useSqlFileStream = fullSize > BlobStorage.MinimumSizeForFileStreamInBytes; - } - else + if (blobProvider != BlobStorageBase.BuiltInProvider) { - useSqlFileStream = false; blobProvider.Allocate(ctx); blobProviderName = blobProvider.GetType().FullName; blobProviderData = BlobStorageContext.SerializeBlobProviderData(ctx.BlobProviderData); } - var sql = InsertStagingBinaryStartScript + - (BlobStorage.FileStreamEnabled ? InsertStagingBinaryFsScript : InsertStagingBinaryScript) + - InsertStagingBinaryEndScript; try { - using (var cmd = new SqlProcedure { CommandText = sql, CommandType = CommandType.Text }) + using (var cmd = new SqlProcedure { CommandText = InsertStagingBinaryScript, CommandType = CommandType.Text }) { cmd.Parameters.Add("@VersionId", SqlDbType.Int).Value = versionId; cmd.Parameters.Add("@PropertyTypeId", SqlDbType.Int).Value = propertyTypeId; cmd.Parameters.Add("@Size", SqlDbType.BigInt).Value = fullSize; - cmd.Parameters.Add("@UseSqlFileStream", SqlDbType.TinyInt).Value = useSqlFileStream ? 2 : 0; cmd.Parameters.Add("@BlobProvider", SqlDbType.NVarChar, 450).Value = blobProviderName != null ? (object)blobProviderName : DBNull.Value; cmd.Parameters.Add("@BlobProviderData", SqlDbType.NVarChar, int.MaxValue).Value = blobProviderData != null ? (object)blobProviderData : DBNull.Value; @@ -882,7 +700,7 @@ public bool CleanupFiles() // delete bytes from the blob storage var provider = BlobStorageBase.GetProvider(providerName); - var ctx = new BlobStorageContext(provider, providerData) { VersionId = 0, PropertyTypeId = 0, FileId = fileId, Length = size, UseFileStream = false }; + var ctx = new BlobStorageContext(provider, providerData) { VersionId = 0, PropertyTypeId = 0, FileId = fileId, Length = size }; ctx.Provider.Delete(ctx); } diff --git a/src/BlobStorage/Properties/AssemblyInfo.cs b/src/BlobStorage/Properties/AssemblyInfo.cs index a3f157a7c..0d55299a1 100644 --- a/src/BlobStorage/Properties/AssemblyInfo.cs +++ b/src/BlobStorage/Properties/AssemblyInfo.cs @@ -3,22 +3,9 @@ using System.Runtime.InteropServices; [assembly: InternalsVisibleTo("SenseNet.Tests")] +[assembly: InternalsVisibleTo("SenseNet.BlobStorage.IntegrationTests")] [assembly: InternalsVisibleTo("SenseNet.ContentRepository.Tests")] [assembly: InternalsVisibleTo("SenseNet.Search.Lucene29.Tests")] -#if DEBUG -[assembly: AssemblyTitle("SenseNet.BlobStorage (Debug)")] -#else -[assembly: AssemblyTitle("SenseNet.BlobStorage (Release)")] -#endif - -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("Sense/Net Inc.")] -[assembly: AssemblyCopyright("Copyright © Sense/Net Inc.")] -[assembly: AssemblyProduct("sensenet")] [assembly: AssemblyTrademark("Sense/Net Inc.")] [assembly: AssemblyCulture("")] -[assembly: AssemblyVersion("7.2.0.0")] -[assembly: AssemblyFileVersion("7.2.0.0")] -[assembly: AssemblyInformationalVersion("7.2.0")] diff --git a/src/BlobStorage/SenseNet.BlobStorage.csproj b/src/BlobStorage/SenseNet.BlobStorage.csproj index 9566dd1d2..1331fdc60 100644 --- a/src/BlobStorage/SenseNet.BlobStorage.csproj +++ b/src/BlobStorage/SenseNet.BlobStorage.csproj @@ -1,121 +1,31 @@ - - + + - Debug - AnyCPU - {4E6722B5-AC95-494C-80A5-A4D80CC502B5} - Library - Properties - SenseNet.ContentRepository.Storage - SenseNet.BlobStorage - v4.6.1 - 512 - SAK - SAK - SAK - SAK - + netstandard2.0 + 7.3.0 + kavics,tusmester + Sense/Net Inc. + Copyright © Sense/Net Inc. + https://github.com/SenseNet/sensenet/blob/master/LICENSE + https://github.com/SenseNet/sensenet + https://raw.githubusercontent.com/SenseNet/sn-resources/master/images/sn-icon/sensenet-icon-64.png + https://github.com/SenseNet/sensenet.git + git + sensenet blob storage + See release notes on GitHub. + true - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - bin\Debug\SenseNet.BlobStorage.XML + + + bin\Release\netstandard2.0\SenseNet.BlobStorage.xml - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - bin\Release\SenseNet.BlobStorage.xml - - - - ..\packages\Newtonsoft.Json.11.0.2\lib\net45\Newtonsoft.Json.dll - - - ..\packages\SenseNet.Tools.3.0.0\lib\netstandard2.0\SenseNet.Tools.dll - - - - - ..\packages\System.Configuration.ConfigurationManager.4.5.0\lib\net461\System.Configuration.ConfigurationManager.dll - - - - - ..\packages\System.Data.SqlClient.4.5.1\lib\net461\System.Data.SqlClient.dll - - - ..\packages\System.Diagnostics.EventLog.4.5.0\lib\net461\System.Diagnostics.EventLog.dll - - - - - ..\packages\System.Security.AccessControl.4.5.0\lib\net461\System.Security.AccessControl.dll - - - ..\packages\System.Security.Permissions.4.5.0\lib\net461\System.Security.Permissions.dll - - - ..\packages\System.Security.Principal.Windows.4.5.0\lib\net461\System.Security.Principal.Windows.dll - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - {A453E920-29C0-45CD-984C-0D8E3631B1E3} - SenseNet.Common - + + - - - Designer - + - - - \ No newline at end of file + + diff --git a/src/BlobStorage/SenseNet.BlobStorage.nuspec b/src/BlobStorage/SenseNet.BlobStorage.nuspec deleted file mode 100644 index 4fdc1c966..000000000 --- a/src/BlobStorage/SenseNet.BlobStorage.nuspec +++ /dev/null @@ -1,25 +0,0 @@ - - - - SenseNet.BlobStorage - 7.2.0 - sensenet BlobStorage library - kavics,aniko,lajos,tusmester - Sense/Net - https://github.com/SenseNet/sensenet/blob/master/LICENSE - https://github.com/SenseNet/sensenet - https://raw.githubusercontent.com/SenseNet/sn-resources/master/images/sn-icon/sensenet-icon-64.png - false - BlobStorage library for the sensenet platform containing the base API for handling binaries directly. - See release notes on GitHub. - Copyright © Sense/Net Inc. - sensenet ecm ecms blob storage - - - - - - - - - \ No newline at end of file diff --git a/src/BlobStorage/packages.config b/src/BlobStorage/packages.config deleted file mode 100644 index 2478f64a8..000000000 --- a/src/BlobStorage/packages.config +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/src/Common/Properties/AssemblyInfo.cs b/src/Common/Properties/AssemblyInfo.cs index 6b347f192..5c4c9872c 100644 --- a/src/Common/Properties/AssemblyInfo.cs +++ b/src/Common/Properties/AssemblyInfo.cs @@ -3,6 +3,7 @@ using System.Runtime.InteropServices; [assembly: InternalsVisibleTo("SenseNet.Tests")] +[assembly: InternalsVisibleTo("SenseNet.BlobStorage.IntegrationTests")] [assembly: InternalsVisibleTo("SenseNet.Packaging.Tests")] [assembly: InternalsVisibleTo("SenseNet.Packaging.IntegrationTests")] diff --git a/src/ContentRepository/Properties/AssemblyInfo.cs b/src/ContentRepository/Properties/AssemblyInfo.cs index b7b234825..8448bbbe5 100644 --- a/src/ContentRepository/Properties/AssemblyInfo.cs +++ b/src/ContentRepository/Properties/AssemblyInfo.cs @@ -3,6 +3,7 @@ using System.Runtime.InteropServices; [assembly: InternalsVisibleTo("SenseNet.Tests")] +[assembly: InternalsVisibleTo("SenseNet.BlobStorage.IntegrationTests")] [assembly: InternalsVisibleTo("SenseNet.ContentRepository.Tests")] [assembly: InternalsVisibleTo("SenseNet.Packaging.Tests")] [assembly: InternalsVisibleTo("SenseNet.Packaging.IntegrationTests")] diff --git a/src/ContentRepository/SenseNet.ContentRepository.csproj b/src/ContentRepository/SenseNet.ContentRepository.csproj index 5479cb586..688987892 100644 --- a/src/ContentRepository/SenseNet.ContentRepository.csproj +++ b/src/ContentRepository/SenseNet.ContentRepository.csproj @@ -556,7 +556,7 @@ - {4E6722B5-AC95-494C-80A5-A4D80CC502B5} + {c250c071-6acd-42e0-9ffc-63283afb8c6c} SenseNet.BlobStorage diff --git a/src/SenseNet.sln b/src/SenseNet.sln index 9829474de..b7d1ef1cd 100644 --- a/src/SenseNet.sln +++ b/src/SenseNet.sln @@ -16,8 +16,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SenseNet.Configuration", "C EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SnAdminRuntime", "Tools\SnAdminRuntime\SnAdminRuntime.csproj", "{891B1FD9-CA73-4129-8D1D-D6663F01866C}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SenseNet.BlobStorage", "BlobStorage\SenseNet.BlobStorage.csproj", "{4E6722B5-AC95-494C-80A5-A4D80CC502B5}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SenseNet.Common", "Common\SenseNet.Common.csproj", "{A453E920-29C0-45CD-984C-0D8E3631B1E3}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{6D908666-E47F-47A7-A7E5-C696B9CD517A}" @@ -47,14 +45,12 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SnAdminRuntime.Tests", "Tes EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SenseNet.Packaging.Tests", "Tests\SenseNet.Packaging.Tests\SenseNet.Packaging.Tests.csproj", "{6B711835-9172-4F07-9FC3-BA79C7DFA916}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SenseNet.Packaging.IntegrationTests", "Tests\SenseNet.Packaging.IntegrationTests\SenseNet.Packaging.IntegrationTests.csproj", "{CDEDC6DA-4DB2-4AA9-9257-0313C87BD9FE}" -EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SenseNet.Search.Tests", "Tests\SenseNet.Search.Tests\SenseNet.Search.Tests.csproj", "{43E6E75C-2410-464D-B7D6-36F8ACF85A17}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SenseNet.Search.IntegrationTests", "Tests\SenseNet.Search.IntegrationTests\SenseNet.Search.IntegrationTests.csproj", "{11506B62-CDBB-40FB-AEDC-ABB393B3AC4D}" -EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SenseNet.Services.OData.Tests", "Tests\SenseNet.Services.OData.Tests\SenseNet.Services.OData.Tests.csproj", "{0CB6D0A8-A477-4382-9F5A-C5BEBD2648AA}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SenseNet.BlobStorage", "BlobStorage\SenseNet.BlobStorage.csproj", "{C250C071-6ACD-42E0-9FFC-63283AFB8C6C}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -127,22 +123,6 @@ Global {891B1FD9-CA73-4129-8D1D-D6663F01866C}.Release|Mixed Platforms.Build.0 = Release|Any CPU {891B1FD9-CA73-4129-8D1D-D6663F01866C}.Release|x64.ActiveCfg = Release|Any CPU {891B1FD9-CA73-4129-8D1D-D6663F01866C}.Release|x86.ActiveCfg = Release|Any CPU - {4E6722B5-AC95-494C-80A5-A4D80CC502B5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {4E6722B5-AC95-494C-80A5-A4D80CC502B5}.Debug|Any CPU.Build.0 = Debug|Any CPU - {4E6722B5-AC95-494C-80A5-A4D80CC502B5}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {4E6722B5-AC95-494C-80A5-A4D80CC502B5}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {4E6722B5-AC95-494C-80A5-A4D80CC502B5}.Debug|x64.ActiveCfg = Debug|Any CPU - {4E6722B5-AC95-494C-80A5-A4D80CC502B5}.Debug|x64.Build.0 = Debug|Any CPU - {4E6722B5-AC95-494C-80A5-A4D80CC502B5}.Debug|x86.ActiveCfg = Debug|Any CPU - {4E6722B5-AC95-494C-80A5-A4D80CC502B5}.Debug|x86.Build.0 = Debug|Any CPU - {4E6722B5-AC95-494C-80A5-A4D80CC502B5}.Release|Any CPU.ActiveCfg = Release|Any CPU - {4E6722B5-AC95-494C-80A5-A4D80CC502B5}.Release|Any CPU.Build.0 = Release|Any CPU - {4E6722B5-AC95-494C-80A5-A4D80CC502B5}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {4E6722B5-AC95-494C-80A5-A4D80CC502B5}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {4E6722B5-AC95-494C-80A5-A4D80CC502B5}.Release|x64.ActiveCfg = Release|Any CPU - {4E6722B5-AC95-494C-80A5-A4D80CC502B5}.Release|x64.Build.0 = Release|Any CPU - {4E6722B5-AC95-494C-80A5-A4D80CC502B5}.Release|x86.ActiveCfg = Release|Any CPU - {4E6722B5-AC95-494C-80A5-A4D80CC502B5}.Release|x86.Build.0 = Release|Any CPU {A453E920-29C0-45CD-984C-0D8E3631B1E3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {A453E920-29C0-45CD-984C-0D8E3631B1E3}.Debug|Any CPU.Build.0 = Debug|Any CPU {A453E920-29C0-45CD-984C-0D8E3631B1E3}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU @@ -303,22 +283,6 @@ Global {6B711835-9172-4F07-9FC3-BA79C7DFA916}.Release|x64.Build.0 = Release|Any CPU {6B711835-9172-4F07-9FC3-BA79C7DFA916}.Release|x86.ActiveCfg = Release|Any CPU {6B711835-9172-4F07-9FC3-BA79C7DFA916}.Release|x86.Build.0 = Release|Any CPU - {CDEDC6DA-4DB2-4AA9-9257-0313C87BD9FE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {CDEDC6DA-4DB2-4AA9-9257-0313C87BD9FE}.Debug|Any CPU.Build.0 = Debug|Any CPU - {CDEDC6DA-4DB2-4AA9-9257-0313C87BD9FE}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {CDEDC6DA-4DB2-4AA9-9257-0313C87BD9FE}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {CDEDC6DA-4DB2-4AA9-9257-0313C87BD9FE}.Debug|x64.ActiveCfg = Debug|Any CPU - {CDEDC6DA-4DB2-4AA9-9257-0313C87BD9FE}.Debug|x64.Build.0 = Debug|Any CPU - {CDEDC6DA-4DB2-4AA9-9257-0313C87BD9FE}.Debug|x86.ActiveCfg = Debug|Any CPU - {CDEDC6DA-4DB2-4AA9-9257-0313C87BD9FE}.Debug|x86.Build.0 = Debug|Any CPU - {CDEDC6DA-4DB2-4AA9-9257-0313C87BD9FE}.Release|Any CPU.ActiveCfg = Release|Any CPU - {CDEDC6DA-4DB2-4AA9-9257-0313C87BD9FE}.Release|Any CPU.Build.0 = Release|Any CPU - {CDEDC6DA-4DB2-4AA9-9257-0313C87BD9FE}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {CDEDC6DA-4DB2-4AA9-9257-0313C87BD9FE}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {CDEDC6DA-4DB2-4AA9-9257-0313C87BD9FE}.Release|x64.ActiveCfg = Release|Any CPU - {CDEDC6DA-4DB2-4AA9-9257-0313C87BD9FE}.Release|x64.Build.0 = Release|Any CPU - {CDEDC6DA-4DB2-4AA9-9257-0313C87BD9FE}.Release|x86.ActiveCfg = Release|Any CPU - {CDEDC6DA-4DB2-4AA9-9257-0313C87BD9FE}.Release|x86.Build.0 = Release|Any CPU {43E6E75C-2410-464D-B7D6-36F8ACF85A17}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {43E6E75C-2410-464D-B7D6-36F8ACF85A17}.Debug|Any CPU.Build.0 = Debug|Any CPU {43E6E75C-2410-464D-B7D6-36F8ACF85A17}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU @@ -335,22 +299,6 @@ Global {43E6E75C-2410-464D-B7D6-36F8ACF85A17}.Release|x64.Build.0 = Release|Any CPU {43E6E75C-2410-464D-B7D6-36F8ACF85A17}.Release|x86.ActiveCfg = Release|Any CPU {43E6E75C-2410-464D-B7D6-36F8ACF85A17}.Release|x86.Build.0 = Release|Any CPU - {11506B62-CDBB-40FB-AEDC-ABB393B3AC4D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {11506B62-CDBB-40FB-AEDC-ABB393B3AC4D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {11506B62-CDBB-40FB-AEDC-ABB393B3AC4D}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {11506B62-CDBB-40FB-AEDC-ABB393B3AC4D}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {11506B62-CDBB-40FB-AEDC-ABB393B3AC4D}.Debug|x64.ActiveCfg = Debug|Any CPU - {11506B62-CDBB-40FB-AEDC-ABB393B3AC4D}.Debug|x64.Build.0 = Debug|Any CPU - {11506B62-CDBB-40FB-AEDC-ABB393B3AC4D}.Debug|x86.ActiveCfg = Debug|Any CPU - {11506B62-CDBB-40FB-AEDC-ABB393B3AC4D}.Debug|x86.Build.0 = Debug|Any CPU - {11506B62-CDBB-40FB-AEDC-ABB393B3AC4D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {11506B62-CDBB-40FB-AEDC-ABB393B3AC4D}.Release|Any CPU.Build.0 = Release|Any CPU - {11506B62-CDBB-40FB-AEDC-ABB393B3AC4D}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {11506B62-CDBB-40FB-AEDC-ABB393B3AC4D}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {11506B62-CDBB-40FB-AEDC-ABB393B3AC4D}.Release|x64.ActiveCfg = Release|Any CPU - {11506B62-CDBB-40FB-AEDC-ABB393B3AC4D}.Release|x64.Build.0 = Release|Any CPU - {11506B62-CDBB-40FB-AEDC-ABB393B3AC4D}.Release|x86.ActiveCfg = Release|Any CPU - {11506B62-CDBB-40FB-AEDC-ABB393B3AC4D}.Release|x86.Build.0 = Release|Any CPU {0CB6D0A8-A477-4382-9F5A-C5BEBD2648AA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {0CB6D0A8-A477-4382-9F5A-C5BEBD2648AA}.Debug|Any CPU.Build.0 = Debug|Any CPU {0CB6D0A8-A477-4382-9F5A-C5BEBD2648AA}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU @@ -367,6 +315,22 @@ Global {0CB6D0A8-A477-4382-9F5A-C5BEBD2648AA}.Release|x64.Build.0 = Release|Any CPU {0CB6D0A8-A477-4382-9F5A-C5BEBD2648AA}.Release|x86.ActiveCfg = Release|Any CPU {0CB6D0A8-A477-4382-9F5A-C5BEBD2648AA}.Release|x86.Build.0 = Release|Any CPU + {C250C071-6ACD-42E0-9FFC-63283AFB8C6C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C250C071-6ACD-42E0-9FFC-63283AFB8C6C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C250C071-6ACD-42E0-9FFC-63283AFB8C6C}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {C250C071-6ACD-42E0-9FFC-63283AFB8C6C}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {C250C071-6ACD-42E0-9FFC-63283AFB8C6C}.Debug|x64.ActiveCfg = Debug|Any CPU + {C250C071-6ACD-42E0-9FFC-63283AFB8C6C}.Debug|x64.Build.0 = Debug|Any CPU + {C250C071-6ACD-42E0-9FFC-63283AFB8C6C}.Debug|x86.ActiveCfg = Debug|Any CPU + {C250C071-6ACD-42E0-9FFC-63283AFB8C6C}.Debug|x86.Build.0 = Debug|Any CPU + {C250C071-6ACD-42E0-9FFC-63283AFB8C6C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C250C071-6ACD-42E0-9FFC-63283AFB8C6C}.Release|Any CPU.Build.0 = Release|Any CPU + {C250C071-6ACD-42E0-9FFC-63283AFB8C6C}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {C250C071-6ACD-42E0-9FFC-63283AFB8C6C}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {C250C071-6ACD-42E0-9FFC-63283AFB8C6C}.Release|x64.ActiveCfg = Release|Any CPU + {C250C071-6ACD-42E0-9FFC-63283AFB8C6C}.Release|x64.Build.0 = Release|Any CPU + {C250C071-6ACD-42E0-9FFC-63283AFB8C6C}.Release|x86.ActiveCfg = Release|Any CPU + {C250C071-6ACD-42E0-9FFC-63283AFB8C6C}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -377,7 +341,6 @@ Global {B72529C8-FEB1-49F5-B08B-56055B58F296} = {2997D17C-A736-43E5-B3DD-11D11AC7DF17} {A19F707C-B1C3-45C7-AE38-E7B7F30C1161} = {2997D17C-A736-43E5-B3DD-11D11AC7DF17} {891B1FD9-CA73-4129-8D1D-D6663F01866C} = {875EF569-4684-473D-A2D4-A35B20B4A07C} - {4E6722B5-AC95-494C-80A5-A4D80CC502B5} = {2997D17C-A736-43E5-B3DD-11D11AC7DF17} {A453E920-29C0-45CD-984C-0D8E3631B1E3} = {2997D17C-A736-43E5-B3DD-11D11AC7DF17} {78FEBD73-8BC4-45B9-9B31-D512E1AFAD60} = {2997D17C-A736-43E5-B3DD-11D11AC7DF17} {CF157DCB-B973-42B4-948A-F6643EB6216D} = {C68D256D-7D40-4E33-8A2B-B1625538B138} @@ -388,10 +351,9 @@ Global {1CF177B1-BCF9-4634-AD71-9DC6D0E58AB7} = {C68D256D-7D40-4E33-8A2B-B1625538B138} {4FB57308-8B47-4232-A97B-0E784A2DCD49} = {C68D256D-7D40-4E33-8A2B-B1625538B138} {6B711835-9172-4F07-9FC3-BA79C7DFA916} = {C68D256D-7D40-4E33-8A2B-B1625538B138} - {CDEDC6DA-4DB2-4AA9-9257-0313C87BD9FE} = {C68D256D-7D40-4E33-8A2B-B1625538B138} {43E6E75C-2410-464D-B7D6-36F8ACF85A17} = {C68D256D-7D40-4E33-8A2B-B1625538B138} - {11506B62-CDBB-40FB-AEDC-ABB393B3AC4D} = {C68D256D-7D40-4E33-8A2B-B1625538B138} {0CB6D0A8-A477-4382-9F5A-C5BEBD2648AA} = {C68D256D-7D40-4E33-8A2B-B1625538B138} + {C250C071-6ACD-42E0-9FFC-63283AFB8C6C} = {2997D17C-A736-43E5-B3DD-11D11AC7DF17} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {7D903DEB-CA0B-43D8-BD9D-820BB1453C4C} diff --git a/src/Storage/Configuration/Providers.cs b/src/Storage/Configuration/Providers.cs index 5e54ae622..19876c788 100644 --- a/src/Storage/Configuration/Providers.cs +++ b/src/Storage/Configuration/Providers.cs @@ -96,7 +96,13 @@ public virtual DataProvider DataProvider #region private Lazy _blobMetaDataProvider = new Lazy private Lazy _blobMetaDataProvider = - new Lazy(() => new MsSqlBlobMetaDataProvider()); + new Lazy(() => + { + var blobMetaClassName = BlobStorage.MetadataProviderClassName; + return string.IsNullOrEmpty(blobMetaClassName) + ? new MsSqlBlobMetaDataProvider() + : CreateProviderInstance(blobMetaClassName, "BlobMetaDataProvider"); + }); public virtual IBlobStorageMetaDataProvider BlobMetaDataProvider { get { return _blobMetaDataProvider.Value; } diff --git a/src/Storage/Data/RepositoryConfiguration.cs b/src/Storage/Data/RepositoryConfiguration.cs index c10b1dcb5..132a97d88 100644 --- a/src/Storage/Data/RepositoryConfiguration.cs +++ b/src/Storage/Data/RepositoryConfiguration.cs @@ -12,10 +12,6 @@ public static class RepositoryConfiguration { #region SECTION: BlobStorage, data, common - [Obsolete("Use Configuration.BlobStorage.FileStreamEnabled instead.")] - public static bool FileStreamEnabled => Configuration.BlobStorage.FileStreamEnabled; - [Obsolete("Use Configuration.BlobStorage.MinimumSizeForFileStreamInBytes instead.")] - public static int MinimumSizeForFileStreamInBytes => Configuration.BlobStorage.MinimumSizeForFileStreamInBytes; [Obsolete("Use Configuration.BlobStorage.MinimumSizeForBlobProviderInBytes instead.")] public static int MinimumSizeForBlobProviderInBytes => Configuration.BlobStorage.MinimumSizeForBlobProviderInBytes; diff --git a/src/Storage/Data/SqlClient/Scripts/EnableFilestream.sql b/src/Storage/Data/SqlClient/Scripts/EnableFilestream.sql deleted file mode 100644 index d414b4f49..000000000 --- a/src/Storage/Data/SqlClient/Scripts/EnableFilestream.sql +++ /dev/null @@ -1,219 +0,0 @@ -/**************************************************************/ -/**************** Enable FILESTREAM on database ***************/ -/**************************************************************/ - --- set access level -EXEC sp_configure filestream_access_level, 2 -RECONFIGURE - -DECLARE @errorHappened tinyint; -DECLARE @Db_Data_Path nvarchar(1000); -DECLARE @Db_Name nvarchar(200); - -SET @errorHappened = 0; - --- get current database name -SELECT @Db_Name = DB_NAME(); - --- find physical path of the database and create a folder there -SELECT @Db_Data_Path = -( - SELECT LEFT(physical_name, LEN(physical_name) - CHARINDEX('\',REVERSE(physical_name)) + 1) + @Db_Name + 'Files' - FROM sys.master_files mf - INNER JOIN sys.[databases] d - ON mf.[database_id] = d.[database_id] - WHERE d.[name] = @Db_Name AND type = 0 -) - -BEGIN TRY -IF NOT EXISTS (SELECT * FROM sys.filegroups WHERE name = 'SNFileGroup') - BEGIN - DECLARE @sql varchar(1000); - SET @sql = N' - ALTER DATABASE [' + @Db_Name + '] - ADD FILEGROUP SNFileGroup CONTAINS FILESTREAM - - ALTER DATABASE [' + @Db_Name + '] - ADD FILE ( NAME = ''SenseNetContentRepository_files'', FILENAME = '''+ @Db_Data_Path + N''') TO FILEGROUP SNFileGroup - - PRINT(''FILEGROUP and FILE added to database.'');'; - - EXEC(@sql); - - END -ELSE - BEGIN - PRINT('FILEGROUP already exists, filegroup and file creation skipped.'); - END -END TRY -BEGIN CATCH - SET @errorHappened = 1; - RAISERROR('FILEGROUP could not be created.', 1, 1); - GOTO SKIPPED; -END CATCH - -/**************************************************************/ -/*** Add UNIQUE constraint to the binary table if necessary ***/ -/**************************************************************/ - -DECLARE @GuidConstraint int; - -SELECT @GuidConstraint = COUNT(CONSTRAINT_NAME) -FROM INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE -WHERE TABLE_NAME = 'Files' AND COLUMN_NAME = 'RowGuid' - -IF (@GuidConstraint = 0) -BEGIN - ALTER TABLE Files - ADD UNIQUE (RowGuid) - - PRINT('UNIQUE constraint added to RowGuid column.'); -END -ELSE -BEGIN - PRINT('RowGuid column already has a UNIQUE constraint.'); -END - - -/**************************************************************/ -/********* Add FILESTREAM column to the Files table **********/ -/**************************************************************/ - -IF EXISTS(SELECT * FROM sys.columns WHERE Name = N'FileStream' and Object_ID = Object_ID(N'Files')) - BEGIN - PRINT('FILESTREAM column already exists.'); - END -ELSE - BEGIN - --This needs to be a dynamic SQL, otherwise compilation would - --fail if the Filestream were already set and added to the table... - execute ('ALTER TABLE dbo.Files SET (FILESTREAM_ON = SNFileGroup) - ALTER TABLE dbo.Files ADD [FileStream] VARBINARY(MAX) FILESTREAM NULL'); - - PRINT('FILESTREAM column added.'); - END - -/**************************************************************/ -/******************** Drop stored procedures ******************/ -/**************************************************************/ - -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[proc_BinaryProperty_Update]') AND type in (N'P', N'PC')) ---OK -DROP PROCEDURE [dbo].[proc_BinaryProperty_Update] - -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[proc_BinaryProperty_GetPointer]') AND type in (N'P', N'PC')) ---OK -DROP PROCEDURE [dbo].[proc_BinaryProperty_GetPointer] - -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[proc_BinaryProperty_WriteStream]') AND type in (N'P', N'PC')) --OK -DROP PROCEDURE [dbo].[proc_BinaryProperty_WriteStream] - -PRINT('Old stored procedures dropped.'); - -/**************************************************************/ -/****************** Re-create stored procedures ***************/ -/**************************************************************/ - -IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[proc_BinaryProperty_Update]') AND type in (N'P', N'PC')) -BEGIN -EXEC dbo.sp_executesql @statement = N'CREATE PROCEDURE [dbo].[proc_BinaryProperty_Update] -( - @BinaryPropertyId int, - @ContentType nvarchar(450), - @FileNameWithoutExtension nvarchar(450), - @Extension nvarchar(50), - @Size bigint, - @Checksum varchar(200), - @BlobProvider nvarchar(450), - @BlobProviderData nvarchar(max) -) -AS -DECLARE @FileId int -SELECT @FileId = FileId FROM BinaryProperties WHERE BinaryPropertyId = @BinaryPropertyId - -DECLARE @EnsureNewFileRow tinyint -IF (@BlobProvider IS NULL) AND (EXISTS (SELECT FileId FROM Files WHERE @FileId = FileId AND BlobProvider IS NOT NULL)) - SET @EnsureNewFileRow = 1 -ELSE - SET @EnsureNewFileRow = 0 - -IF (@EnsureNewFileRow = 1) OR (EXISTS (SELECT FileId FROM BinaryProperties WHERE FileId = @FileId AND BinaryPropertyId != @BinaryPropertyId)) BEGIN - INSERT INTO Files (ContentType, FileNameWithoutExtension, Extension, [Size], [BlobProvider], [BlobProviderData], [Checksum], [Stream], [FileStream]) - VALUES (@ContentType, @FileNameWithoutExtension, @Extension, @Size, @BlobProvider, @BlobProviderData, - CASE WHEN (@Size <= 0) THEN NULL ELSE @Checksum END, - NULL, - CASE WHEN (@Size <= 0) THEN NULL ELSE CONVERT(varbinary, '''') END) - - SELECT @FileId = @@IDENTITY - - UPDATE BinaryProperties SET FileId = @FileId WHERE BinaryPropertyId = @BinaryPropertyId - -END -ELSE BEGIN - - UPDATE Files - SET ContentType = @ContentType, - FileNameWithoutExtension = @FileNameWithoutExtension, - Extension = @Extension, - [Size] = @Size, - [BlobProvider] = @BlobProvider, - [BlobProviderData] = @BlobProviderData, - [Checksum] = CASE WHEN (@Size <= 0) THEN NULL ELSE @Checksum END, - [Stream] = NULL, - [FileStream] = CASE WHEN (@Size <= 0) THEN NULL ELSE CONVERT(varbinary, '''') END - WHERE FileId = @FileId - -END - -SELECT @FileId, FileStream.PathName(), GET_FILESTREAM_TRANSACTION_CONTEXT() -FROM Files WHERE FileId = @FileId' -END - -IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[proc_BinaryProperty_GetPointer]') AND type in (N'P', N'PC')) -BEGIN -EXEC dbo.sp_executesql @statement = N'CREATE PROCEDURE [dbo].[proc_BinaryProperty_GetPointer] -( - @VersionId int, - @PropertyTypeId int, - @FileId int OUTPUT, - @Length int OUTPUT, - @TransactionContext varbinary(max) OUTPUT, - @FilePath nvarchar(4000) OUTPUT -) -AS - SELECT @FileId = F.FileId, - @Length = CASE WHEN F.FileStream IS NULL THEN DATALENGTH(F.Stream) ELSE DATALENGTH(F.FileStream) END, - @TransactionContext = GET_FILESTREAM_TRANSACTION_CONTEXT(), - @FilePath = F.FileStream.PathName() - FROM BinaryProperties B - JOIN Files F ON F.FileId = B.FileId - WHERE B.VersionId = @VersionId AND B.PropertyTypeId = @PropertyTypeId AND F.Staging IS NULL -' -END - - -IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[proc_BinaryProperty_WriteStream]') AND type in (N'P', N'PC')) -BEGIN -EXEC dbo.sp_executesql @statement = N'CREATE PROCEDURE [dbo].[proc_BinaryProperty_WriteStream] -( - @Id int, - @Offset int, - @Value varbinary(max), - @UseFileStream tinyint -) -AS - IF(@UseFileStream = 1) - UPDATE Files SET FileStream = @Value, Stream = NULL WHERE FileId = @Id; - ELSE - UPDATE Files SET Stream = @Value, FileStream = NULL WHERE FileId = @Id; -' -END - - -PRINT('New stored procedures created.'); - -SKIPPED: -IF (@errorHappened > 0) -BEGIN - PRINT('Script stopped with error.'); -END - -GO \ No newline at end of file diff --git a/src/Storage/Properties/AssemblyInfo.cs b/src/Storage/Properties/AssemblyInfo.cs index 051600af4..41fd98e7d 100644 --- a/src/Storage/Properties/AssemblyInfo.cs +++ b/src/Storage/Properties/AssemblyInfo.cs @@ -3,6 +3,7 @@ using System.Runtime.InteropServices; [assembly: InternalsVisibleTo("SenseNet.Tests")] +[assembly: InternalsVisibleTo("SenseNet.BlobStorage.IntegrationTests")] [assembly: InternalsVisibleTo("SenseNet.ContentRepository.Tests")] [assembly: InternalsVisibleTo("SenseNet.Packaging.Tests")] [assembly: InternalsVisibleTo("SenseNet.Packaging.IntegrationTests")] diff --git a/src/Storage/SenseNet.Storage.csproj b/src/Storage/SenseNet.Storage.csproj index 70ccf81da..d7efb340b 100644 --- a/src/Storage/SenseNet.Storage.csproj +++ b/src/Storage/SenseNet.Storage.csproj @@ -421,14 +421,13 @@ - - {4e6722b5-ac95-494c-80a5-a4d80cc502b5} + {c250c071-6acd-42e0-9ffc-63283afb8c6c} SenseNet.BlobStorage diff --git a/src/Tests/SenseNet.ContentRepository.Tests/SenseNet.ContentRepository.Tests.csproj b/src/Tests/SenseNet.ContentRepository.Tests/SenseNet.ContentRepository.Tests.csproj index b502ef2be..fbe65ee93 100644 --- a/src/Tests/SenseNet.ContentRepository.Tests/SenseNet.ContentRepository.Tests.csproj +++ b/src/Tests/SenseNet.ContentRepository.Tests/SenseNet.ContentRepository.Tests.csproj @@ -126,10 +126,6 @@ - - {4e6722b5-ac95-494c-80a5-a4d80cc502b5} - SenseNet.BlobStorage - {a453e920-29c0-45cd-984c-0d8e3631b1e3} SenseNet.Common diff --git a/src/Tests/SenseNet.Packaging.IntegrationTests/Implementations/PackagingTestLogger.cs b/src/Tests/SenseNet.Packaging.IntegrationTests/Implementations/PackagingTestLogger.cs deleted file mode 100644 index 21c17bd9e..000000000 --- a/src/Tests/SenseNet.Packaging.IntegrationTests/Implementations/PackagingTestLogger.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System.Text; - -namespace SenseNet.Packaging.IntegrationTests.Implementations -{ - public class PackagingTestLogger : IPackagingLogger - { - public LogLevel AcceptedLevel => LogLevel.File; - private readonly StringBuilder _sb; - - public string LogFilePath => "[in memory]"; - - public PackagingTestLogger(StringBuilder sb) - { - _sb = sb; - } - - public void Initialize(LogLevel level, string logFilePath) { } - public void WriteTitle(string title) - { - _sb.AppendLine("================================"); - _sb.AppendLine(title); - _sb.AppendLine("================================"); - } - public void WriteMessage(string message) - { - _sb.AppendLine(message); - } - } -} diff --git a/src/Tests/SenseNet.Packaging.IntegrationTests/PackagingMsSqlTests.cs b/src/Tests/SenseNet.Packaging.IntegrationTests/PackagingMsSqlTests.cs deleted file mode 100644 index bc4d5d9e5..000000000 --- a/src/Tests/SenseNet.Packaging.IntegrationTests/PackagingMsSqlTests.cs +++ /dev/null @@ -1,1045 +0,0 @@ -using System.Data; -using System.Linq; -using System.Text; -using System.Xml; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using SenseNet.Configuration; -using SenseNet.ContentRepository; -using SenseNet.ContentRepository.Storage; -using SenseNet.ContentRepository.Storage.Data; -using SenseNet.Packaging.Steps; -using System; -using System.IO; -using System.Collections.Generic; -using SenseNet.Packaging.IntegrationTests.Implementations; -using SenseNet.Tests; - -namespace SenseNet.Packaging.IntegrationTests -{ - public class TestStepThatCreatesThePackagingTable : Step - { - public override void Execute(ExecutionContext context) - { - PackagingMsSqlTests.InstallPackagesTable(); - } - } - - [TestClass] - public class PackagingMsSqlTests : TestBase - { - private static readonly string ConnectionString = - //"Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=sensenet;Data Source=(local)"; - //"Data Source=.;Initial Catalog=sensenet;User ID=sa;Password=sa;Pooling=False"; - @"Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=sn7tests;Data Source=.\SQL2016"; - - private static readonly string DropPackagesTableSql = @" -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[Packages]') AND type in (N'U')) -DROP TABLE [dbo].[Packages] -"; - - - private static readonly string InstallPackagesTableSql = @" -CREATE TABLE [dbo].[Packages]( - [Id] [int] IDENTITY(1,1) NOT NULL, - [PackageType] [varchar](50) NOT NULL, - [ComponentId] [nvarchar](450) NULL, - [ComponentVersion] [varchar](50) NULL, - [ReleaseDate] [datetime] NOT NULL, - [ExecutionDate] [datetime] NOT NULL, - [ExecutionResult] [varchar](50) NOT NULL, - [ExecutionError] [nvarchar](max) NULL, - [Description] [nvarchar](1000) NULL, - [Manifest] [nvarchar](max) NULL, - CONSTRAINT [PK_Packages] PRIMARY KEY CLUSTERED -( - [Id] ASC -)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] -) ON [PRIMARY] -"; - - private static StringBuilder _log; - - [ClassInitialize] - public static void InitializeDatabase(TestContext context) - { - DropPackagesTable(); - InstallPackagesTable(); - } - [TestInitialize] - public void InitializeTest() - { - // preparing logger - _log = new StringBuilder(); - var loggers = new[] { new PackagingTestLogger(_log) }; - var loggerAcc = new PrivateType(typeof(Logger)); - loggerAcc.SetStaticField("_loggers", loggers); - - // preparing database - ConnectionStrings.ConnectionString = ConnectionString; - var proc = DataProvider.CreateDataProcedure("DELETE FROM [Packages]"); - proc.CommandType = CommandType.Text; - proc.ExecuteNonQuery(); - proc = DataProvider.CreateDataProcedure("DBCC CHECKIDENT ('[Packages]', RESEED, 1)"); - proc.CommandType = CommandType.Text; - proc.ExecuteNonQuery(); - - RepositoryVersionInfo.Reset(); - } - - // ========================================= Checking dependency tests - - [TestMethod] - public void Packaging_SQL_DependencyCheck_MissingDependency() - { - var expectedErrorType = PackagingExceptionType.DependencyNotFound; - var actualErrorType = PackagingExceptionType.NotDefined; - - // action - try - { - ExecutePhases(@" - - Component2 - 2017-01-01 - 1.0 - - - - - Package is running. - - "); - Assert.Fail("PackagingException was not thrown."); - } - catch (PackagingException e) - { - actualErrorType = e.ErrorType; - } - - // assert - Assert.AreEqual(actualErrorType, expectedErrorType); - } - [TestMethod] - public void Packaging_SQL_DependencyCheck_CannotInstallExistingComponent() - { - ExecutePhases(@" - - MyCompany.MyComponent - 2017-01-01 - 1.0 - - Package is running. - - "); - - // action - try - { - ExecutePhases(@" - - MyCompany.MyComponent - 2017-01-01 - 1.1 - - Package is running. - - "); - Assert.Fail("PackagingException was not thrown."); - } - catch (PackagingException e) - { - Assert.AreEqual(PackagingExceptionType.CannotInstallExistingComponent, e.ErrorType); - } - } - [TestMethod] - public void Packaging_SQL_DependencyCheck_CannotUpdateMissingComponent() - { - try - { - ExecutePhases(@" - - Component2 - 2017-01-01 - 1.1 - - Package is running. - - "); - Assert.Fail("PackagingException was not thrown."); - } - catch (PackagingException e) - { - Assert.AreEqual(PackagingExceptionType.CannotUpdateMissingComponent, e.ErrorType); - } - } - [TestMethod] - public void Packaging_SQL_DependencyCheck_TargetVersionTooSmall() - { - ExecutePhases(@" - - MyCompany.MyComponent - 2017-01-01 - 1.0 - - Package is running. - - "); - - // action - try - { - ExecutePhases(@" - - MyCompany.MyComponent - 2017-01-01 - 1.0 - - Package is running. - - "); - Assert.Fail("PackagingException was not thrown."); - } - catch (PackagingException e) - { - Assert.AreEqual(PackagingExceptionType.TargetVersionTooSmall, e.ErrorType); - } - } - - [TestMethod] - public void Packaging_SQL_DependencyCheck_DependencyVersion() - { - ExecutePhases(@" - - Component1 - 2017-01-01 - 1.0 - - Package is running. - - "); - - // action - try - { - ExecutePhases(@" - - Component2 - 2017-01-01 - 1.1 - - - - - Package is running. - - "); - Assert.Fail("PackagingException was not thrown."); - } - catch (PackagingException e) - { - Assert.AreEqual(PackagingExceptionType.DependencyVersion, e.ErrorType); - } - } - [TestMethod] - public void Packaging_SQL_DependencyCheck_DependencyMinimumVersion() - { - ExecutePhases(@" - - Component1 - 2017-01-01 - 1.0 - - Package is running. - - "); - - // action - try - { - ExecutePhases(@" - - Component2 - 2017-01-01 - 1.1 - - - - - Package is running. - - "); - Assert.Fail("PackagingException was not thrown."); - } - catch (PackagingException e) - { - Assert.AreEqual(PackagingExceptionType.DependencyMinimumVersion, e.ErrorType); - } - } - [TestMethod] - public void Packaging_SQL_DependencyCheck_DependencyMaximumVersion() - { - ExecutePhases(@" - - Component1 - 2017-01-01 - 3.0 - - Package is running. - - "); - - // action - try - { - ExecutePhases(@" - - Component2 - 2017-01-01 - 2.1 - - - - - Package is running. - - "); - Assert.Fail("PackagingException was not thrown."); - } - catch (PackagingException e) - { - Assert.AreEqual(PackagingExceptionType.DependencyMaximumVersion, e.ErrorType); - } - } - [TestMethod] - public void Packaging_SQL_DependencyCheck_DependencyMinimumVersionExclusive() - { - ExecutePhases(@" - - Component1 - 2017-01-01 - 1.0 - - Package is running. - - "); - - // action - try - { - ExecutePhases(@" - - Component2 - 2017-01-01 - 1.1 - - - - - Package is running. - - "); - Assert.Fail("PackagingException was not thrown."); - } - catch (PackagingException e) - { - Assert.AreEqual(PackagingExceptionType.DependencyMinimumVersion, e.ErrorType); - } - } - [TestMethod] - public void Packaging_SQL_DependencyCheck_DependencyMaximumVersionExclusive() - { - ExecutePhases(@" - - Component1 - 2017-01-01 - 3.0 - - Package is running. - - "); - - // action - try - { - ExecutePhases(@" - - Component2 - 2017-01-01 - 2.0 - - - - - Package is running. - - "); - Assert.Fail("PackagingException was not thrown."); - } - catch (PackagingException e) - { - Assert.AreEqual(PackagingExceptionType.DependencyMaximumVersion, e.ErrorType); - } - } - - [TestMethod] - public void Packaging_SQL_DependencyCheck_LoggingDependencies() - { - DependencyCheckLoggingDependencies(_log); - } - internal void DependencyCheckLoggingDependencies(StringBuilder logger) - { - for (var i = 0; i < 9; i++) - { - ExecutePhases($@" - - Component{i + 1} - 2017-01-01 - {i + 1}.0 - "); - } - logger.Clear(); - - // action - ExecutePhases(@" - - MyCompany.MyComponent - 2017-01-02 - 1.2 - - - - - - - - - - - - "); - - // check - var log = logger.ToString(); - var relevantLines = new List(); - using (var reader = new StringReader(log)) - { - string line; - while ((line = reader.ReadLine()) != null) - { - line = line.Trim(); - if (line.StartsWith("Component") && !line.StartsWith("ComponentId")) - relevantLines.Add(line); - } - } - - Assert.AreEqual("Component1: 1.0 = 1.0 (current)", relevantLines[0]); - Assert.AreEqual("Component2: 1.0 <= 2.0 (current)", relevantLines[1]); - Assert.AreEqual("Component3: 3.0 (current) <= 9.0", relevantLines[2]); - Assert.AreEqual("Component4: 1.0 < 4.0 (current)", relevantLines[3]); - Assert.AreEqual("Component5: 5.0 (current) <= 9.0", relevantLines[4]); - Assert.AreEqual("Component6: 1.0 <= 6.0 (current) <= 10.0", relevantLines[5]); - Assert.AreEqual("Component7: 1.0 <= 7.0 (current) <= 10.0", relevantLines[6]); - Assert.AreEqual("Component8: 1.0 < 8.0 (current) < 10.0", relevantLines[7]); - Assert.AreEqual("Component9: 1.0 < 9.0 (current) < 10.0", relevantLines[8]); - } - - // ========================================= Component lifetime tests - - [TestMethod] - public void Packaging_SQL_Install_NoSteps() - { - var manifestXml = new XmlDocument(); - manifestXml.LoadXml(@" - - Component42 - 2017-01-01 - 4.42 - "); - - // action - ExecutePhase(manifestXml, 0); - - // check - Assert.AreEqual(1, RepositoryVersionInfo.Instance.Components.Count()); - Assert.AreEqual(1, RepositoryVersionInfo.Instance.InstalledPackages.Count()); - var component = RepositoryVersionInfo.Instance.Components.FirstOrDefault(); - Assert.IsNotNull(component); - Assert.AreEqual("Component42", component.ComponentId); - Assert.AreEqual("4.42", component.Version.ToString()); - Assert.IsNotNull(component.AcceptableVersion); - Assert.AreEqual("4.42", component.AcceptableVersion.ToString()); - var pkg = RepositoryVersionInfo.Instance.InstalledPackages.FirstOrDefault(); - Assert.IsNotNull(pkg); - Assert.AreEqual("Component42", pkg.ComponentId); - Assert.AreEqual(ExecutionResult.Successful, pkg.ExecutionResult); - Assert.AreEqual(PackageType.Install, pkg.PackageType); - Assert.AreEqual("4.42", pkg.ComponentVersion.ToString()); - } - [TestMethod] - public void Packaging_SQL_Install_ThreePhases() - { - var manifestXml = new XmlDocument(); - manifestXml.LoadXml(@" - - Component42 - 2017-01-01 - 4.42 - - Package is running. Phase-1 - Package is running. Phase-2 - Package is running. Phase-3 - - "); - - // phase 1 - ExecutePhase(manifestXml, 0); - - // validate state after phase 1 - var verInfo = RepositoryVersionInfo.Instance; - Assert.IsFalse(verInfo.Components.Any()); - Assert.IsTrue(verInfo.InstalledPackages.Any()); - var pkg = RepositoryVersionInfo.Instance.InstalledPackages.FirstOrDefault(); - Assert.IsNotNull(pkg); - Assert.AreEqual("Component42", pkg.ComponentId); - Assert.AreEqual(ExecutionResult.Unfinished, pkg.ExecutionResult); - Assert.AreEqual(PackageType.Install, pkg.PackageType); - Assert.AreEqual("4.42", pkg.ComponentVersion.ToString()); - - // phase 2 - ExecutePhase(manifestXml, 1); - - // validate state after phase 2 - verInfo = RepositoryVersionInfo.Instance; - Assert.IsFalse(verInfo.Components.Any()); - Assert.IsTrue(verInfo.InstalledPackages.Any()); - pkg = RepositoryVersionInfo.Instance.InstalledPackages.FirstOrDefault(); - Assert.IsNotNull(pkg); - Assert.AreEqual("Component42", pkg.ComponentId); - Assert.AreEqual(ExecutionResult.Unfinished, pkg.ExecutionResult); - Assert.AreEqual(PackageType.Install, pkg.PackageType); - Assert.AreEqual("4.42", pkg.ComponentVersion.ToString()); - - // phase 3 - ExecutePhase(manifestXml, 2); - - // validate state after phase 3 - var component = RepositoryVersionInfo.Instance.Components.FirstOrDefault(); - Assert.IsNotNull(component); - Assert.AreEqual("Component42", component.ComponentId); - Assert.AreEqual("4.42", component.Version.ToString()); - Assert.IsNotNull(component.AcceptableVersion); - Assert.AreEqual("4.42", component.AcceptableVersion.ToString()); - pkg = RepositoryVersionInfo.Instance.InstalledPackages.FirstOrDefault(); - Assert.IsNotNull(pkg); - Assert.AreEqual("Component42", pkg.ComponentId); - Assert.AreEqual(ExecutionResult.Successful, pkg.ExecutionResult); - Assert.AreEqual(PackageType.Install, pkg.PackageType); - Assert.AreEqual("4.42", pkg.ComponentVersion.ToString()); - - Assert.AreEqual(1, RepositoryVersionInfo.Instance.Components.Count()); - Assert.AreEqual(1, RepositoryVersionInfo.Instance.InstalledPackages.Count()); - } - - [TestMethod] - public void Packaging_SQL_Patch_ThreePhases() - { - ExecutePhases(@" - - MyCompany.MyComponent - 2017-01-01 - 1.0 - - Package is running. - - "); - - var manifestXml = new XmlDocument(); - manifestXml.LoadXml(@" - - MyCompany.MyComponent - 2017-01-02 - 1.2 - - Package is running. Phase-1 - Package is running. Phase-2 - Package is running. Phase-3 - - "); - - // phase 1 - ExecutePhase(manifestXml, 0); - - // validate state after phase 1 - var component = RepositoryVersionInfo.Instance.Components.FirstOrDefault(); - Assert.IsNotNull(component); - Assert.AreEqual("MyCompany.MyComponent", component.ComponentId); - Assert.AreEqual("1.2", component.Version.ToString()); - Assert.IsNotNull(component.AcceptableVersion); - Assert.AreEqual("1.0", component.AcceptableVersion.ToString()); - var pkg = RepositoryVersionInfo.Instance.InstalledPackages.LastOrDefault(); - Assert.IsNotNull(pkg); - Assert.AreEqual("MyCompany.MyComponent", pkg.ComponentId); - Assert.AreEqual(ExecutionResult.Unfinished, pkg.ExecutionResult); - Assert.AreEqual(PackageType.Patch, pkg.PackageType); - Assert.AreEqual("1.2", pkg.ComponentVersion.ToString()); - - // phase 2 - ExecutePhase(manifestXml, 1); - - // validate state after phase 2 - component = RepositoryVersionInfo.Instance.Components.FirstOrDefault(); - Assert.IsNotNull(component); - Assert.AreEqual("MyCompany.MyComponent", component.ComponentId); - Assert.AreEqual("1.2", component.Version.ToString()); - Assert.IsNotNull(component.AcceptableVersion); - Assert.AreEqual("1.0", component.AcceptableVersion.ToString()); - pkg = RepositoryVersionInfo.Instance.InstalledPackages.LastOrDefault(); - Assert.IsNotNull(pkg); - Assert.AreEqual("MyCompany.MyComponent", pkg.ComponentId); - Assert.AreEqual(ExecutionResult.Unfinished, pkg.ExecutionResult); - Assert.AreEqual(PackageType.Patch, pkg.PackageType); - Assert.AreEqual("1.2", pkg.ComponentVersion.ToString()); - - // phase 3 - ExecutePhase(manifestXml, 2); - - // validate state after phase 3 - component = RepositoryVersionInfo.Instance.Components.FirstOrDefault(); - Assert.IsNotNull(component); - Assert.AreEqual("MyCompany.MyComponent", component.ComponentId); - Assert.AreEqual("1.2", component.Version.ToString()); - Assert.IsNotNull(component.AcceptableVersion); - Assert.AreEqual("1.2", component.AcceptableVersion.ToString()); - pkg = RepositoryVersionInfo.Instance.InstalledPackages.LastOrDefault(); - Assert.IsNotNull(pkg); - Assert.AreEqual("MyCompany.MyComponent", pkg.ComponentId); - Assert.AreEqual(ExecutionResult.Successful, pkg.ExecutionResult); - Assert.AreEqual(PackageType.Patch, pkg.PackageType); - Assert.AreEqual("1.2", pkg.ComponentVersion.ToString()); - - Assert.AreEqual(1, RepositoryVersionInfo.Instance.Components.Count()); - Assert.AreEqual(2, RepositoryVersionInfo.Instance.InstalledPackages.Count()); - } - - [TestMethod] - public void Packaging_SQL_Patch_Faulty() - { - ExecutePhases(@" - - MyCompany.MyComponent - 2017-01-01 - 1.0 - - Package is running. - - "); - - // action - try - { - ExecutePhases(@" - - MyCompany.MyComponent - 2017-01-02 - 1.2 - - - - "); - Assert.Fail("PackagingException was not thrown."); - } - catch (Exception) - { - // do not compensate anything - } - - // check - Assert.AreEqual(1, RepositoryVersionInfo.Instance.Components.Count()); - Assert.AreEqual(2, RepositoryVersionInfo.Instance.InstalledPackages.Count()); - var component = RepositoryVersionInfo.Instance.Components.FirstOrDefault(); - Assert.IsNotNull(component); - Assert.AreEqual("MyCompany.MyComponent", component.ComponentId); - Assert.AreEqual("1.2", component.Version.ToString()); - Assert.IsNotNull(component.AcceptableVersion); - Assert.AreEqual("1.0", component.AcceptableVersion.ToString()); - var pkg = RepositoryVersionInfo.Instance.InstalledPackages.LastOrDefault(); - Assert.IsNotNull(pkg); - Assert.AreEqual("MyCompany.MyComponent", pkg.ComponentId); - Assert.AreEqual(ExecutionResult.Faulty, pkg.ExecutionResult); - Assert.AreEqual(PackageType.Patch, pkg.PackageType); - Assert.AreEqual("1.2", pkg.ComponentVersion.ToString()); - } - [TestMethod] - public void Packaging_SQL_Patch_FixFaulty() - { - ExecutePhases(@" - - MyCompany.MyComponent - 2017-01-01 - 1.0 - - Package is running. - - "); - - try - { - ExecutePhases(@" - - MyCompany.MyComponent - 2017-01-02 - 1.2 - - - - "); - Assert.Fail("PackagingException was not thrown."); - } - catch (Exception) - { - // do not compensate anything - } - - // action - ExecutePhases(@" - - MyCompany.MyComponent - 2017-01-02 - 1.2 - - Package is running. - - "); - - // check - Assert.AreEqual(1, RepositoryVersionInfo.Instance.Components.Count()); - Assert.AreEqual(3, RepositoryVersionInfo.Instance.InstalledPackages.Count()); - var component = RepositoryVersionInfo.Instance.Components.FirstOrDefault(); - Assert.IsNotNull(component); - Assert.AreEqual("MyCompany.MyComponent", component.ComponentId); - Assert.AreEqual("1.2", component.Version.ToString()); - Assert.IsNotNull(component.AcceptableVersion); - Assert.AreEqual("1.2", component.AcceptableVersion.ToString()); - var pkg = RepositoryVersionInfo.Instance.InstalledPackages.LastOrDefault(); - Assert.IsNotNull(pkg); - Assert.AreEqual("MyCompany.MyComponent", pkg.ComponentId); - Assert.AreEqual(ExecutionResult.Successful, pkg.ExecutionResult); - Assert.AreEqual(PackageType.Patch, pkg.PackageType); - Assert.AreEqual("1.2", pkg.ComponentVersion.ToString()); - } - [TestMethod] - public void Packaging_SQL_Patch_FixMoreFaulty() - { - ExecutePhases(@" - - MyCompany.MyComponent - 2017-01-01 - 1.0 - - Package is running. - - "); - - for (int i = 0; i < 2; i++) - { - try - { - ExecutePhases(@" - - MyCompany.MyComponent - 2017-01-02 - 1.2 - - - - "); - Assert.Fail("PackagingException was not thrown."); - } - catch (Exception) - { - // do not compensate anything - } - } - - // action - ExecutePhases(@" - - MyCompany.MyComponent - 2017-01-02 - 1.2 - - Package is running. - - "); - - // check - Assert.AreEqual(1, RepositoryVersionInfo.Instance.Components.Count()); - Assert.AreEqual(4, RepositoryVersionInfo.Instance.InstalledPackages.Count()); - var component = RepositoryVersionInfo.Instance.Components.FirstOrDefault(); - Assert.IsNotNull(component); - Assert.AreEqual("MyCompany.MyComponent", component.ComponentId); - Assert.AreEqual("1.2", component.Version.ToString()); - Assert.IsNotNull(component.AcceptableVersion); - Assert.AreEqual("1.2", component.AcceptableVersion.ToString()); - var pkg = RepositoryVersionInfo.Instance.InstalledPackages.LastOrDefault(); - Assert.IsNotNull(pkg); - Assert.AreEqual("MyCompany.MyComponent", pkg.ComponentId); - Assert.AreEqual(ExecutionResult.Successful, pkg.ExecutionResult); - Assert.AreEqual(PackageType.Patch, pkg.PackageType); - Assert.AreEqual("1.2", pkg.ComponentVersion.ToString()); - } - - // ========================================= RepositoryVersionInfo queries - - [TestMethod] - public void Packaging_SQL_VersionInfo_Empty() - { - var verInfo = RepositoryVersionInfo.Instance; - var components = verInfo.Components.ToArray(); - var packages = verInfo.InstalledPackages.ToArray(); - Assert.AreEqual(0, components.Length); - Assert.AreEqual(0, packages.Length); - } - [TestMethod] - public void Packaging_SQL_VersionInfo_OnlyUnfinished() - { - SavePackage("C1", "1.0", "01:00", "2016-01-01", PackageType.Install, ExecutionResult.Unfinished); - - // action - var verInfo = RepositoryVersionInfo.Instance; - - // check - var components = verInfo.Components.ToArray(); - var packages = verInfo.InstalledPackages.ToArray(); - Assert.AreEqual(0, components.Length); - Assert.AreEqual(1, packages.Length); - } - [TestMethod] - public void Packaging_SQL_VersionInfo_OnlyFaulty() - { - SavePackage("C1", "1.0", "01:00", "2016-01-01", PackageType.Install, ExecutionResult.Faulty); - - // action - var verInfo = RepositoryVersionInfo.Instance; - - // check - var components = verInfo.Components.ToArray(); - var packages = verInfo.InstalledPackages.ToArray(); - Assert.AreEqual(0, components.Length); - Assert.AreEqual(1, packages.Length); - } - [TestMethod] - public void Packaging_SQL_VersionInfo_Complex() - { - SavePackage("C1", "1.0", "01:00", "2016-01-01", PackageType.Install, ExecutionResult.Successful); - SavePackage("C2", "1.0", "02:00", "2016-01-02", PackageType.Install, ExecutionResult.Successful); - SavePackage("C1", "1.1", "03:00", "2016-01-03", PackageType.Patch, ExecutionResult.Faulty); - SavePackage("C1", "1.1", "04:00", "2016-01-03", PackageType.Patch, ExecutionResult.Faulty); - SavePackage("C1", "1.2", "05:00", "2016-01-06", PackageType.Patch, ExecutionResult.Successful); - SavePackage("C2", "1.1", "06:00", "2016-01-07", PackageType.Patch, ExecutionResult.Unfinished); - SavePackage("C2", "1.2", "07:00", "2016-01-08", PackageType.Patch, ExecutionResult.Unfinished); - SavePackage("C3", "1.0", "08:00", "2016-01-09", PackageType.Install, ExecutionResult.Faulty); - SavePackage("C3", "2.0", "08:00", "2016-01-09", PackageType.Install, ExecutionResult.Faulty); - - // action - var verInfo = RepositoryVersionInfo.Instance; - - // check - var actual = string.Join(" | ", verInfo.Components - .OrderBy(a => a.ComponentId) - .Select(a => $"{a.ComponentId}: {a.AcceptableVersion} ({a.Version})") - .ToArray()); - // - var expected = "C1: 1.2 (1.2) | C2: 1.0 (1.2)"; - Assert.AreEqual(expected, actual); - Assert.AreEqual(9, verInfo.InstalledPackages.Count()); - } - - [TestMethod] - public void Packaging_SQL_VersionInfo_MultipleInstall() - { - const string packageId = "C1"; - SavePackage(packageId, "1.0", "01:00", "2016-01-01", PackageType.Install, ExecutionResult.Successful); - SavePackage(packageId, "1.0", "02:00", "2016-01-02", PackageType.Install, ExecutionResult.Successful); - SavePackage(packageId, "1.1", "03:00", "2016-01-03", PackageType.Install, ExecutionResult.Faulty); - SavePackage(packageId, "1.2", "04:00", "2016-01-04", PackageType.Install, ExecutionResult.Faulty); - SavePackage("C2", "1.0", "05:00", "2016-01-05", PackageType.Install, ExecutionResult.Successful); - SavePackage(packageId, "1.0", "06:00", "2016-01-06", PackageType.Install, ExecutionResult.Successful); - - var verInfo = RepositoryVersionInfo.Instance; - - // check - var actual = string.Join(" | ", verInfo.Components - .OrderBy(a => a.ComponentId) - .Select(a => $"{a.ComponentId}: {a.AcceptableVersion} ({a.Version})") - .ToArray()); - - // we expect a separate line for every Install package execution - var expected = "C1: 1.0 (1.2) | C1: 1.0 (1.2) | C1: 1.0 (1.2) | C2: 1.0 (1.0)"; - Assert.AreEqual(expected, actual); - Assert.AreEqual(6, verInfo.InstalledPackages.Count()); - } - - // ========================================= Storing manifest - - [TestMethod] - public void Packaging_SQL_Manifest_StoredButNotLoaded() - { - // prepare xml source - var manifest = @" - - Component42 - 2017-01-01 - 4.42 - - Package is running. Phase-1 - - "; - var xml = new XmlDocument(); - xml.LoadXml(manifest); - var expected = xml.OuterXml; - - // store - ExecutePhases(manifest); - - // load - var verInfo = RepositoryVersionInfo.Instance; - - // manifest is not explicitly loaded - var package = verInfo.InstalledPackages.FirstOrDefault(); - Assert.IsNull(package?.Manifest); - - // load manifest explicitly - PackageManager.Storage.LoadManifest(package); - var actual = package?.Manifest; - Assert.AreEqual(expected, actual); - } - - // ========================================= Package deletion - - [TestMethod] - public void Packaging_SQL_DeleteOne() - { - SavePackage("C1", "1.0", "00:00", "2016-01-01", PackageType.Install, ExecutionResult.Unfinished); - SavePackage("C1", "1.0", "01:00", "2016-01-01", PackageType.Install, ExecutionResult.Faulty); - SavePackage("C1", "1.0", "02:00", "2016-01-01", PackageType.Install, ExecutionResult.Successful); - SavePackage("C1", "1.1", "03:00", "2016-01-03", PackageType.Patch, ExecutionResult.Faulty); - SavePackage("C1", "1.1", "04:00", "2016-01-03", PackageType.Patch, ExecutionResult.Faulty); - SavePackage("C1", "1.1", "05:00", "2016-01-06", PackageType.Patch, ExecutionResult.Successful); - SavePackage("C1", "1.2", "06:00", "2016-01-07", PackageType.Patch, ExecutionResult.Unfinished); - SavePackage("C1", "1.2", "07:00", "2016-01-08", PackageType.Patch, ExecutionResult.Unfinished); - SavePackage("C1", "1.2", "08:00", "2016-01-09", PackageType.Patch, ExecutionResult.Faulty); - SavePackage("C1", "1.2", "09:00", "2016-01-09", PackageType.Patch, ExecutionResult.Faulty); - SavePackage("C1", "1.2", "10:00", "2016-01-09", PackageType.Patch, ExecutionResult.Successful); - - // action: delete all faulty and unfinished - var packs = RepositoryVersionInfo.Instance.InstalledPackages - .Where(p => p.ExecutionResult != ExecutionResult.Successful); - foreach (var package in packs) - PackageManager.Storage.DeletePackage(package); - RepositoryVersionInfo.Reset(); - - // check - var actual = string.Join(" | ", RepositoryVersionInfo.Instance.InstalledPackages - .OrderBy(p => p.ComponentVersion) - .Select(p => $"{p.PackageType.ToString()[0]}:{p.ComponentVersion}-{p.ExecutionDate.Hour}") - .ToArray()); - var expected = "I:1.0-2 | P:1.1-5 | P:1.2-10"; - Assert.AreEqual(expected, actual); - } - [TestMethod] - public void Packaging_SQL_DeleteAll() - { - SavePackage("C1", "1.0", "02:00", "2016-01-01", PackageType.Install, ExecutionResult.Successful); - SavePackage("C1", "1.1", "05:00", "2016-01-06", PackageType.Patch, ExecutionResult.Successful); - SavePackage("C1", "1.2", "10:00", "2016-01-09", PackageType.Patch, ExecutionResult.Successful); - - // action - PackageManager.Storage.DeleteAllPackages(); - - // check - Assert.IsFalse(RepositoryVersionInfo.Instance.InstalledPackages.Any()); - } - - /*================================================= tools */ - - internal static void DropPackagesTable() - { - ExecuteSqlCommand(DropPackagesTableSql); - } - internal static void InstallPackagesTable() - { - ExecuteSqlCommand(InstallPackagesTableSql); - } - private static void ExecuteSqlCommand(string sql) - { - ConnectionStrings.ConnectionString = ConnectionString; - var proc = DataProvider.CreateDataProcedure(sql); - proc.CommandType = CommandType.Text; - proc.ExecuteNonQuery(); - } - - /*--------------------------------------------------------*/ - - private void SavePackage(string id, string version, string execTime, string releaseDate, PackageType packageType, ExecutionResult result) - { - var package = new Package - { - ComponentId = id, - ComponentVersion = Version.Parse(version), - Description = $"{id}-Description", - ExecutionDate = DateTime.Parse($"2017-03-30 {execTime}"), - ReleaseDate = DateTime.Parse(releaseDate), - ExecutionError = null, - ExecutionResult = result, - PackageType = packageType, - Manifest = $"" - }; - PackageManager.Storage.SavePackage(package); - } - - internal static Manifest ParseManifestHead(string manifestXml) - { - var xml = new XmlDocument(); - xml.LoadXml(manifestXml); - var manifest = new Manifest(); - Manifest.ParseHead(xml, manifest); - return manifest; - } - internal static Manifest ParseManifest(string manifestXml, int currentPhase) - { - var xml = new XmlDocument(); - xml.LoadXml(manifestXml); - return Manifest.Parse(xml, currentPhase, true, new PackageParameter[0]); - } - - internal static PackagingResult ExecutePhases(string manifestXml, TextWriter console = null) - { - var xml = new XmlDocument(); - xml.LoadXml(manifestXml); - return ExecutePhases(xml, console); - } - internal static PackagingResult ExecutePhases(XmlDocument manifestXml, TextWriter console = null) - { - var phase = -1; - var errors = 0; - PackagingResult result; - do - { - result = ExecutePhase(manifestXml, ++phase, console ?? new StringWriter()); - errors += result.Errors; - } while (result.NeedRestart); - result.Errors = errors; - return result; - } - internal static PackagingResult ExecutePhase(XmlDocument manifestXml, int phase, TextWriter console = null) - { - var manifest = Manifest.Parse(manifestXml, phase, true, new PackageParameter[0]); - var executionContext = ExecutionContext.CreateForTest("packagePath", "targetPath", new string[0], "sandboxPath", manifest, phase, manifest.CountOfPhases, null, console ?? new StringWriter()); - var result = PackageManager.ExecuteCurrentPhase(manifest, executionContext); - RepositoryVersionInfo.Reset(); - return result; - } - - } -} diff --git a/src/Tests/SenseNet.Packaging.IntegrationTests/Properties/AssemblyInfo.cs b/src/Tests/SenseNet.Packaging.IntegrationTests/Properties/AssemblyInfo.cs deleted file mode 100644 index 51113ca1d..000000000 --- a/src/Tests/SenseNet.Packaging.IntegrationTests/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System.Reflection; -using System.Runtime.InteropServices; - -[assembly: AssemblyTitle("SenseNet.Packaging.IntegrationTests")] - -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("Sense/Net Inc.")] -[assembly: AssemblyCopyright("Copyright © Sense/Net Inc.")] -[assembly: AssemblyProduct("sensenet")] -[assembly: AssemblyTrademark("Sense/Net Inc.")] -[assembly: AssemblyCulture("")] -[assembly: AssemblyVersion("7.1.1.0")] -[assembly: AssemblyFileVersion("7.1.1.0")] -[assembly: AssemblyInformationalVersion("7.1.1")] - -[assembly: ComVisible(false)] -[assembly: Guid("cf049086-0872-4f55-af6d-6177245cc59e")] \ No newline at end of file diff --git a/src/Tests/SenseNet.Packaging.IntegrationTests/SenseNet.Packaging.IntegrationTests.csproj b/src/Tests/SenseNet.Packaging.IntegrationTests/SenseNet.Packaging.IntegrationTests.csproj deleted file mode 100644 index 0a387c7e9..000000000 --- a/src/Tests/SenseNet.Packaging.IntegrationTests/SenseNet.Packaging.IntegrationTests.csproj +++ /dev/null @@ -1,117 +0,0 @@ - - - - - Debug - AnyCPU - {CDEDC6DA-4DB2-4AA9-9257-0313C87BD9FE} - Library - Properties - SenseNet.Packaging.IntegrationTests - SenseNet.Packaging.IntegrationTests - v4.6.1 - 512 - {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - 15.0 - $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages - False - UnitTest - - - - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - - ..\..\packages\MSTest.TestFramework.1.2.0\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.dll - - - ..\..\packages\MSTest.TestFramework.1.2.0\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions.dll - - - ..\..\packages\SenseNet.Tools.3.0.1\lib\netstandard2.0\SenseNet.Tools.dll - - - - - ..\..\packages\System.Configuration.ConfigurationManager.4.5.0\lib\net461\System.Configuration.ConfigurationManager.dll - - - - - ..\..\packages\System.Data.SqlClient.4.5.1\lib\net461\System.Data.SqlClient.dll - - - ..\..\packages\System.Diagnostics.EventLog.4.5.0\lib\net461\System.Diagnostics.EventLog.dll - - - - - ..\..\packages\System.Security.AccessControl.4.5.0\lib\net461\System.Security.AccessControl.dll - - - ..\..\packages\System.Security.Permissions.4.5.0\lib\net461\System.Security.Permissions.dll - - - ..\..\packages\System.Security.Principal.Windows.4.5.0\lib\net461\System.Security.Principal.Windows.dll - - - - - - - - - - - - - Designer - - - - - {a453e920-29c0-45cd-984c-0d8e3631b1e3} - SenseNet.Common - - - {786e6165-ca02-45a9-bf58-207a45d7d6df} - SenseNet.ContentRepository - - - {5db4ddba-81f6-4d81-943a-18f3178b3355} - SenseNet.Storage - - - {A0909E8F-E039-4080-A259-676CFD38CCD1} - SenseNet.Tests - - - - - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - - - \ No newline at end of file diff --git a/src/Tests/SenseNet.Packaging.IntegrationTests/packages.config b/src/Tests/SenseNet.Packaging.IntegrationTests/packages.config deleted file mode 100644 index faecead06..000000000 --- a/src/Tests/SenseNet.Packaging.IntegrationTests/packages.config +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/src/Tests/SenseNet.Search.IntegrationTests/ActivityQueueSelectorTests.cs b/src/Tests/SenseNet.Search.IntegrationTests/ActivityQueueSelectorTests.cs deleted file mode 100644 index a1781634b..000000000 --- a/src/Tests/SenseNet.Search.IntegrationTests/ActivityQueueSelectorTests.cs +++ /dev/null @@ -1,264 +0,0 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; -using SenseNet.ContentRepository; -using SenseNet.ContentRepository.Search; -using SenseNet.ContentRepository.Security; -using SenseNet.ContentRepository.Storage.Data; -using SenseNet.ContentRepository.Storage.Security; -using SenseNet.Diagnostics; -using SenseNet.Search.Indexing; -using System; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.IO; -using System.Linq; -using System.Runtime.CompilerServices; -using System.Text; -using SenseNet.ContentRepository.Search.Indexing; -using SenseNet.ContentRepository.Search.Indexing.Activities; -using SenseNet.Search.Querying; -using SenseNet.Tests; -using SenseNet.Tests.Implementations; - -namespace SenseNet.Search.IntegrationTests -{ - [TestClass] - public class ActivityQueueSelectorTests : TestBase - { - private class IndexingEngineForActivityQueueSelectorTests : IIndexingEngine - { - public bool Running { get; private set; } - - public bool IndexIsCentralized { get; } - - public IndexingEngineForActivityQueueSelectorTests(bool centralized) - { - IndexIsCentralized = centralized; - } - - public void ClearIndex() - { - throw new NotImplementedException(); - } - - public IndexingActivityStatus ReadActivityStatusFromIndex() - { - return IndexingActivityStatus.Startup; - } - - public void ShutDown() - { - Running = false; - } - - public void Start(TextWriter consoleOut) - { - Running = true; - } - - public void WriteActivityStatusToIndex(IndexingActivityStatus state) - { - } - - [SuppressMessage("ReSharper", "AssignNullToNotNullAttribute")] - public void WriteIndex(IEnumerable deletions, IEnumerable updates, IEnumerable additions) - { - var distributed = Environment.StackTrace.Contains(typeof(DistributedIndexingActivityQueue).FullName) ? "DISTRIBUTED" : ""; - var centralized = Environment.StackTrace.Contains(typeof(CentralizedIndexingActivityQueue).FullName) ? "CENTRALIZED" : ""; - _log.AppendLine($"{centralized}{distributed}. deletions: {deletions?.Count() ?? 0}, updates: {updates?.Count() ?? 0}, addition: {additions?.Count() ?? 0}"); - } - - readonly StringBuilder _log = new StringBuilder(); - public string GetLog() - { - return _log.ToString(); - } - } - - private class QueryEngineForActivityQueueSelectorTests : IQueryEngine - { - public QueryResult ExecuteQuery(SnQuery query, IPermissionFilter filter, IQueryContext context) - { - throw new NotImplementedException(); - } - - public QueryResult ExecuteQueryAndProject(SnQuery query, IPermissionFilter filter, IQueryContext context) - { - throw new NotImplementedException(); - } - } - - private class SearchEngineForActivityQueueSelectorTests : ISearchEngine - { - public IIndexingEngine IndexingEngine { get; } - - public IQueryEngine QueryEngine { get; } - - public SearchEngineForActivityQueueSelectorTests(bool centralized) - { - IndexingEngine = new IndexingEngineForActivityQueueSelectorTests(centralized); - QueryEngine = new QueryEngineForActivityQueueSelectorTests(); - } - - public IDictionary GetAnalyzers() - { - throw new NotImplementedException(); - } - - public void SetIndexingInfo(IDictionary indexingInfo) - { - } - - public string GetIndexingLog() - { - return ((IndexingEngineForActivityQueueSelectorTests)IndexingEngine).GetLog(); - } - } - - [TestMethod, TestCategory("IR")] - public void Indexing_ActivitySelector_Distributed() - { - var searchEngine = new SearchEngineForActivityQueueSelectorTests(false); - ActivityQueueSelectorTest(searchEngine, null, s => - { - var nodeName = "Indexing_Distributed"; - var node = new SystemFolder(Repository.Root) { Name = nodeName }; - using (new SystemAccount()) - node.Save(); - - Assert.AreEqual("DISTRIBUTED. deletions: 0, updates: 0, addition: 1\r\n", searchEngine.GetIndexingLog()); - }); - } - [TestMethod, TestCategory("IR")] - public void Indexing_ActivitySelector_Centralized() - { - var searchEngine = new SearchEngineForActivityQueueSelectorTests(true); - ActivityQueueSelectorTest(searchEngine, null, s => - { - var nodeName = "Indexing_Centralized"; - var node = new SystemFolder(Repository.Root) { Name = nodeName }; - using (new SystemAccount()) - node.Save(); - - Assert.AreEqual("CENTRALIZED. deletions: 0, updates: 0, addition: 1\r\n", searchEngine.GetIndexingLog()); - }); - } - - [TestMethod, TestCategory("IR")] - public void Indexing_Centralized_InMemory_ExecuteUnprocessed() - { - var dataProvider = new InMemoryDataProvider(); - var searchEngine = new SearchEngineForActivityQueueSelectorTests(false); - var nodeId = 0; - var versionId = 0; - var path = string.Empty; - ActivityQueueSelectorTest(searchEngine, dataProvider, s => - { - // create a valid version - var nodeName = "Indexing_Centralized_InMemory_ExecuteUnprocessed"; - var node = new SystemFolder(Repository.Root) { Name = nodeName }; - using (new SystemAccount()) - node.Save(); - nodeId = node.Id; - versionId = node.VersionId; - path = node.Path; - }); - - DataProvider.Current.DeleteAllIndexingActivities(); - RegisterActivity(IndexingActivityType.AddDocument, IndexingActivityRunningState.Waiting, nodeId, versionId, path); - RegisterActivity(IndexingActivityType.UpdateDocument, IndexingActivityRunningState.Waiting, nodeId, versionId, path); - RegisterActivity(IndexingActivityType.UpdateDocument, IndexingActivityRunningState.Waiting, nodeId, versionId, path); - - SnTrace.Test.Write("Indexing_Centralized_InMemory_ExecuteUnprocessed ACTION"); - - searchEngine = new SearchEngineForActivityQueueSelectorTests(true); - ActivityQueueSelectorTest(searchEngine, dataProvider, s => - { - var log = searchEngine.GetIndexingLog(); - Assert.AreEqual( - "CENTRALIZED. deletions: 0, updates: 0, addition: 1\r\n" + - "CENTRALIZED. deletions: 0, updates: 1, addition: 0\r\n" + - "CENTRALIZED. deletions: 0, updates: 1, addition: 0\r\n", log); - }); - } - - /* ============================================================================================== */ - - protected void ActivityQueueSelectorTest(ISearchEngine searchEngine, InMemoryDataProvider dataProvider, Action callback, [CallerMemberName]string memberName = "") - { - if(dataProvider == null) - dataProvider = new InMemoryDataProvider(); - var securityDataProvider = GetSecurityDataProvider(dataProvider); - - Configuration.Indexing.IsOuterSearchEngineEnabled = true; - CommonComponents.TransactionFactory = dataProvider; - DistributedApplication.Cache.Reset(); - - var indxManConsole = new StringWriter(); - var repoBuilder = new RepositoryBuilder() - .UseDataProvider(dataProvider) - .UseBlobMetaDataProvider(new InMemoryBlobStorageMetaDataProvider(dataProvider)) - .UseBlobProviderSelector(new InMemoryBlobProviderSelector()) - .UseAccessProvider(new DesktopAccessProvider()) - .UsePermissionFilterFactory(new EverythingAllowedPermissionFilterFactory()) - .UseSearchEngine(searchEngine) - .UseSecurityDataProvider(securityDataProvider) - .UseCacheProvider(new EmptyCache()) - .UseTraceCategories("ContentOperation", "Event", "Repository", "IndexQueue", "Index", "Query") - .DisableNodeObservers() - .EnableNodeObservers(typeof(SettingsCache)) - .StartWorkflowEngine(false) - .SetConsole(indxManConsole); - - using (Repository.Start(repoBuilder)) - { - using (Tests.Tools.Swindle(typeof(SearchManager), "_searchEngineSupport", new SearchEngineSupport())) - { - callback(indxManConsole.ToString()); - } - } - } - - private void RegisterActivity(IndexingActivityType type, IndexingActivityRunningState state, int nodeId, int versionId, string path) - { - IndexingActivityBase activity; - if (type == IndexingActivityType.AddTree || type == IndexingActivityType.RemoveTree) - activity = CreateTreeActivity(type, path, nodeId); - else - activity = CreateActivity(type, path, nodeId, versionId, 9999); - activity.RunningState = state; - - DataProvider.Current.RegisterIndexingActivity(activity); - } - private IndexingActivityBase CreateActivity(IndexingActivityType type, string path, int nodeId, int versionId, long versionTimestamp) - { - var activity = (IndexingActivityBase)IndexingActivityFactory.Instance.CreateActivity(type); - activity.Path = path.ToLowerInvariant(); - activity.NodeId = nodeId; - activity.VersionId = versionId; - activity.VersionTimestamp = versionTimestamp; - - if (activity is DocumentIndexingActivity documentActivity) - { - documentActivity.SetDocument(new IndexDocument()); - documentActivity.Versioning = new VersioningInfo - { - Delete = new int[0], - Reindex = new int[0], - LastDraftVersionId = versionId, - LastPublicVersionId = versionId - }; - } - - return activity; - } - - private IndexingActivityBase CreateTreeActivity(IndexingActivityType type, string path, int nodeId) - { - var activity = (IndexingActivityBase)IndexingActivityFactory.Instance.CreateActivity(type); - activity.Path = path.ToLowerInvariant(); - activity.NodeId = nodeId; - - return activity; - } - } -} diff --git a/src/Tests/SenseNet.Search.IntegrationTests/CentralizedIndexingInMemoryTests.cs b/src/Tests/SenseNet.Search.IntegrationTests/CentralizedIndexingInMemoryTests.cs deleted file mode 100644 index 5e18c117e..000000000 --- a/src/Tests/SenseNet.Search.IntegrationTests/CentralizedIndexingInMemoryTests.cs +++ /dev/null @@ -1,490 +0,0 @@ -using System; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using SenseNet.ContentRepository.Storage.Data; -using System.Linq; -using System.Threading; -using SenseNet.ContentRepository.Search.Indexing; -using SenseNet.ContentRepository.Search.Indexing.Activities; -using SenseNet.Tests; -using SenseNet.Tests.Implementations; - -namespace SenseNet.Search.IntegrationTests -{ - [TestClass] - public class CentralizedIndexingInMemorylTests : TestBase - { - [TestMethod, TestCategory("IR")] - public void Indexing_Centralized_InMemory_RegisterAndReload() - { - using (new Tests.Tools.DataProviderSwindler(new InMemoryDataProvider())) - { - var lastActivityIdBefore = DataProvider.Current.GetLastIndexingActivityId(); - - var timeAtStart = DateTime.UtcNow; - - // avoid rounding errors: reloaded datetime can be less than timeAtStart - // if rounding in sql converts the input to smaller value. - Thread.Sleep(10); - - var activities = new[] - { - CreateActivity(IndexingActivityType.AddDocument, "/Root/42", 42, 42, 99999999, null), - CreateActivity(IndexingActivityType.UpdateDocument, "/Root/43", 43, 43, 99999999, null), - CreateTreeActivity(IndexingActivityType.AddTree, "/Root/44", 44, null), - CreateTreeActivity(IndexingActivityType.RemoveTree, "/Root/45", 45, null), - CreateActivity(IndexingActivityType.Rebuild, "/Root/46", 46, 46, 99999999, null), - }; - - foreach (var activity in activities) - DataProvider.Current.RegisterIndexingActivity(activity); - - // avoid rounding errors: reloaded datetime can be greater than timeAtEnd - // if rounding in sql converts the input to greater value. - Thread.Sleep(10); - - var timeAtEnd = DateTime.UtcNow; - - var lastActivityIdAfter = DataProvider.Current.GetLastIndexingActivityId(); - Assert.AreEqual(lastActivityIdBefore + 5, lastActivityIdAfter); - - var factory = new IndexingActivityFactory(); - - // ---- simulating system start - var unprocessedActivities = DataProvider.Current.LoadIndexingActivities(lastActivityIdBefore + 1, lastActivityIdAfter, 1000, true, factory); - Assert.AreEqual(5, unprocessedActivities.Length); - Assert.AreEqual( - $"{IndexingActivityType.AddDocument}, {IndexingActivityType.UpdateDocument}, {IndexingActivityType.AddTree}, {IndexingActivityType.RemoveTree}, {IndexingActivityType.Rebuild}", - string.Join(", ", unprocessedActivities.Select(x => x.ActivityType.ToString()).ToArray())); - Assert.AreEqual( - "42, 43, 44, 45, 46", - string.Join(", ", unprocessedActivities.Select(x => x.NodeId.ToString()).ToArray())); - Assert.AreEqual( - "42, 43, 0, 0, 46", - string.Join(", ", unprocessedActivities.Select(x => x.VersionId.ToString()).ToArray())); - Assert.AreEqual( - "/root/42, /root/43, /root/44, /root/45, /root/46", - string.Join(", ", unprocessedActivities.Select(x => x.Path))); - - for (int i = 0; i < unprocessedActivities.Length; i++) - { - Assert.AreEqual(lastActivityIdBefore + i + 1, unprocessedActivities[i].Id); - Assert.IsTrue(timeAtStart <= unprocessedActivities[i].CreationDate && unprocessedActivities[i].CreationDate <= timeAtEnd); - Assert.IsTrue(unprocessedActivities[i].IsUnprocessedActivity); - Assert.AreEqual(IndexingActivityRunningState.Waiting, unprocessedActivities[i].RunningState); - Assert.IsNull(unprocessedActivities[i].LockTime); - } - - // ---- simulating runtime maintenance - var loadedActivities = DataProvider.Current.LoadIndexingActivities(lastActivityIdBefore + 1, lastActivityIdAfter, 1000, false, factory); - Assert.AreEqual(5, loadedActivities.Length); - Assert.AreEqual( - $"{IndexingActivityType.AddDocument}, {IndexingActivityType.UpdateDocument}, {IndexingActivityType.AddTree}, {IndexingActivityType.RemoveTree}, {IndexingActivityType.Rebuild}", - string.Join(", ", loadedActivities.Select(x => x.ActivityType.ToString()).ToArray())); - Assert.AreEqual( - "42, 43, 44, 45, 46", - string.Join(", ", loadedActivities.Select(x => x.NodeId.ToString()).ToArray())); - Assert.AreEqual( - "42, 43, 0, 0, 46", - string.Join(", ", loadedActivities.Select(x => x.VersionId.ToString()).ToArray())); - Assert.AreEqual( - "/root/42, /root/43, /root/44, /root/45, /root/46", - string.Join(", ", loadedActivities.Select(x => x.Path))); - - for (int i = 0; i < loadedActivities.Length; i++) - { - Assert.AreEqual(lastActivityIdBefore + i + 1, loadedActivities[i].Id); - Assert.IsTrue(timeAtStart <= loadedActivities[i].CreationDate && loadedActivities[i].CreationDate <= timeAtEnd); - Assert.IsFalse(loadedActivities[i].IsUnprocessedActivity); - Assert.AreEqual(IndexingActivityRunningState.Waiting, unprocessedActivities[i].RunningState); - Assert.IsNull(unprocessedActivities[i].LockTime); - } - - var gaps = new[] { lastActivityIdBefore + 1, lastActivityIdBefore + 2 }; - // ---- simulating system start - var unprocessedActivitiesFromGaps = DataProvider.Current.LoadIndexingActivities(gaps, true, factory); - Assert.AreEqual( - $"{lastActivityIdBefore + 1}, {lastActivityIdBefore + 2}", - string.Join(", ", unprocessedActivitiesFromGaps.Select(x => x.Id.ToString()).ToArray())); - Assert.AreEqual( - "True, True", - string.Join(", ", unprocessedActivitiesFromGaps.Select(x => x.IsUnprocessedActivity.ToString()).ToArray())); - // ---- simulating runtime maintenance - var loadedActivitiesFromGaps = DataProvider.Current.LoadIndexingActivities(gaps, false, factory); - Assert.AreEqual( - $"{lastActivityIdBefore + 1}, {lastActivityIdBefore + 2}", - string.Join(", ", loadedActivitiesFromGaps.Select(x => x.Id.ToString()).ToArray())); - Assert.AreEqual( - "False, False", - string.Join(", ", loadedActivitiesFromGaps.Select(x => x.IsUnprocessedActivity.ToString()).ToArray())); - } - } - - [TestMethod, TestCategory("IR")] - public void Indexing_Centralized_InMemory_UpdateStateToDone() - { - using (new Tests.Tools.DataProviderSwindler(new InMemoryDataProvider())) - { - var lastActivityIdBefore = DataProvider.Current.GetLastIndexingActivityId(); - DataProvider.Current.RegisterIndexingActivity( - CreateActivity( - IndexingActivityType.AddDocument, "/Root/Indexing_Centralized_InMemory_UpdateStateToDone", 42, 42, 99999999, null)); - var lastActivityIdAfter = DataProvider.Current.GetLastIndexingActivityId(); - - var factory = new IndexingActivityFactory(); - var loadedActivities = DataProvider.Current.LoadIndexingActivities(lastActivityIdBefore + 1, lastActivityIdAfter, 1000, false, factory).ToArray(); - if (loadedActivities.Length != 1) - Assert.Inconclusive("Successful test needs one IndexingActivity."); - var loadedActivity = loadedActivities[0]; - if (loadedActivity == null) - Assert.Inconclusive("Successful test needs the existing IndexingActivity."); - if (loadedActivity.RunningState != IndexingActivityRunningState.Waiting) - Assert.Inconclusive("Successful test needs the requirement: ActivityState is IndexingActivityState.Waiting."); - - // action - DataProvider.Current.UpdateIndexingActivityRunningState(loadedActivity.Id, IndexingActivityRunningState.Done); - - // check - var lastActivityIdAfterUpdate = DataProvider.Current.GetLastIndexingActivityId(); - Assert.AreEqual(lastActivityIdAfter, lastActivityIdAfterUpdate); - - loadedActivity = DataProvider.Current.LoadIndexingActivities(lastActivityIdBefore + 1, lastActivityIdAfter, 1000, false, factory).First(); - Assert.AreEqual(IndexingActivityRunningState.Done, loadedActivity.RunningState); - } - } - - [TestMethod, TestCategory("IR")] - public void Indexing_Centralized_InMemory_Allocate01_SelectWaiting() - { - using (new Tests.Tools.DataProviderSwindler(new InMemoryDataProvider())) - { - var start = new[] - { - RegisterActivity(IndexingActivityType.AddDocument, IndexingActivityRunningState.Done, 1, 1, "/Root/Path1"), - RegisterActivity(IndexingActivityType.AddDocument, IndexingActivityRunningState.Running, 2, 2, "/Root/Path2"), - RegisterActivity(IndexingActivityType.AddDocument, IndexingActivityRunningState.Waiting, 3, 3, "/Root/Path3"), - }; - - var allocated = DataProvider.Current.LoadExecutableIndexingActivities(new IndexingActivityFactory(), 10, 60); - - Assert.AreEqual(1, allocated.Length); - Assert.AreEqual(start[2].Id, allocated[0].Id); - } - } - [TestMethod, TestCategory("IR")] - public void Indexing_Centralized_InMemory_Allocate02_IdDependency() - { - using (new Tests.Tools.DataProviderSwindler(new InMemoryDataProvider())) - { - var start = new[] - { - RegisterActivity(IndexingActivityType.AddDocument, IndexingActivityRunningState.Waiting, 1, 1, "/Root/Path1"), - RegisterActivity(IndexingActivityType.UpdateDocument, IndexingActivityRunningState.Waiting, 1, 1, "/Root/Path1"), - RegisterActivity(IndexingActivityType.UpdateDocument, IndexingActivityRunningState.Waiting, 1, 1, "/Root/Path1"), - }; - - var allocated = DataProvider.Current.LoadExecutableIndexingActivities(new IndexingActivityFactory(), 10, 60); - - Assert.AreEqual(1, allocated.Length); - Assert.AreEqual(start[0].Id, allocated[0].Id); - } - } - [TestMethod, TestCategory("IR")] - public void Indexing_Centralized_InMemory_Allocate02_IdDependency_VersionId0() - { - using (new Tests.Tools.DataProviderSwindler(new InMemoryDataProvider())) - { - var start = new[] - { - RegisterActivity(IndexingActivityType.Rebuild, IndexingActivityRunningState.Waiting, 1, 0, "/Root/Path1"), - RegisterActivity(IndexingActivityType.Rebuild, IndexingActivityRunningState.Waiting, 2, 0, "/Root/Path2"), - RegisterActivity(IndexingActivityType.Rebuild, IndexingActivityRunningState.Waiting, 3, 0, "/Root/Path3"), - }; - - var allocated = DataProvider.Current.LoadExecutableIndexingActivities(new IndexingActivityFactory(), 10, 60); - - Assert.AreEqual(3, allocated.Length); - Assert.AreEqual(start[0].Id, allocated[0].Id); - Assert.AreEqual(start[1].Id, allocated[1].Id); - Assert.AreEqual(start[2].Id, allocated[2].Id); - } - } - [TestMethod, TestCategory("IR")] - public void Indexing_Centralized_InMemory_Allocate03_InactiveDependency() - { - using (new Tests.Tools.DataProviderSwindler(new InMemoryDataProvider())) - { - var start = new[] - { - RegisterActivity(IndexingActivityType.AddDocument, IndexingActivityRunningState.Done, 1, 1, "/Root/Path1"), - RegisterActivity(IndexingActivityType.AddDocument, IndexingActivityRunningState.Done, 2, 2, "/Root/Path2"), - RegisterActivity(IndexingActivityType.UpdateDocument, IndexingActivityRunningState.Waiting, 2, 2, "/Root/Path2"), - RegisterActivity(IndexingActivityType.UpdateDocument, IndexingActivityRunningState.Waiting, 2, 2, "/Root/Path2"), - RegisterActivity(IndexingActivityType.UpdateDocument, IndexingActivityRunningState.Waiting, 2, 2, "/Root/Path2"), - }; - - var allocated = DataProvider.Current.LoadExecutableIndexingActivities(new IndexingActivityFactory(), 10, 60); - - Assert.AreEqual(1, allocated.Length); - Assert.AreEqual(start[2].Id, allocated[0].Id); - } - } - [TestMethod, TestCategory("IR")] - public void Indexing_Centralized_InMemory_Allocate04_SelectMore() - { - using (new Tests.Tools.DataProviderSwindler(new InMemoryDataProvider())) - { - var start = new[] - { - RegisterActivity(IndexingActivityType.AddDocument, IndexingActivityRunningState.Done, 1, 1, "/Root/Path1"), // 0 - RegisterActivity(IndexingActivityType.AddDocument, IndexingActivityRunningState.Done, 2, 2, "/Root/Path2"), // 1 - RegisterActivity(IndexingActivityType.UpdateDocument, IndexingActivityRunningState.Waiting, 2, 2, "/Root/Path2"), // 2 - RegisterActivity(IndexingActivityType.UpdateDocument, IndexingActivityRunningState.Waiting, 2, 2, "/Root/Path2"), // 3 - RegisterActivity(IndexingActivityType.UpdateDocument, IndexingActivityRunningState.Waiting, 2, 2, "/Root/Path2"), // 4 - RegisterActivity(IndexingActivityType.AddDocument, IndexingActivityRunningState.Waiting, 3, 3, "/Root/Path3"), // 5 - RegisterActivity(IndexingActivityType.UpdateDocument, IndexingActivityRunningState.Waiting, 3, 3, "/Root/Path3"), // 6 - RegisterActivity(IndexingActivityType.AddDocument, IndexingActivityRunningState.Waiting, 4, 4, "/Root/Path4"), // 7 - RegisterActivity(IndexingActivityType.UpdateDocument, IndexingActivityRunningState.Waiting, 4, 4, "/Root/Path4"), // 8 - }; - - var allocated = DataProvider.Current.LoadExecutableIndexingActivities(new IndexingActivityFactory(), 10, 60); - - Assert.AreEqual(3, allocated.Length); - Assert.AreEqual(start[2].Id, allocated[0].Id); - Assert.AreEqual(start[5].Id, allocated[1].Id); - Assert.AreEqual(start[7].Id, allocated[2].Id); - } - } - [TestMethod, TestCategory("IR")] - public void Indexing_Centralized_InMemory_Allocate05_PathDependency() - { - using (new Tests.Tools.DataProviderSwindler(new InMemoryDataProvider())) - { - var start = new[] - { - RegisterActivity(IndexingActivityType.AddTree, IndexingActivityRunningState.Waiting, 1, 1, "/Root/Path1"), // 0 - RegisterActivity(IndexingActivityType.AddDocument, IndexingActivityRunningState.Waiting, 2, 2, "/Root/Path2"), // 1 - RegisterActivity(IndexingActivityType.UpdateDocument, IndexingActivityRunningState.Waiting, 3, 3, "/Root/Path1/aaa"), // 2 - RegisterActivity(IndexingActivityType.UpdateDocument, IndexingActivityRunningState.Waiting, 4, 4, "/Root/Path1/bbb"), // 3 - RegisterActivity(IndexingActivityType.UpdateDocument, IndexingActivityRunningState.Waiting, 2, 2, "/Root/Path2"), // 4 - RegisterActivity(IndexingActivityType.AddDocument, IndexingActivityRunningState.Waiting, 5, 5, "/Root/Path3/xxx"), // 5 - RegisterActivity(IndexingActivityType.AddTree, IndexingActivityRunningState.Waiting, 6, 6, "/Root/Path3"), // 6 - RegisterActivity(IndexingActivityType.AddDocument, IndexingActivityRunningState.Waiting, 7, 7, "/Root/Path4"), // 7 - }; - - var allocated = DataProvider.Current.LoadExecutableIndexingActivities(new IndexingActivityFactory(), 10, 60); - - Assert.AreEqual(4, allocated.Length); - Assert.AreEqual(start[0].Id, allocated[0].Id); - Assert.AreEqual(start[1].Id, allocated[1].Id); - Assert.AreEqual(start[5].Id, allocated[2].Id); - Assert.AreEqual(start[7].Id, allocated[3].Id); - } - } - [TestMethod, TestCategory("IR")] - public void Indexing_Centralized_InMemory_Allocate06_Timeout() - { - using (new Tests.Tools.DataProviderSwindler(new InMemoryDataProvider())) - { - var start = new[] - { - RegisterActivity(IndexingActivityType.AddDocument, IndexingActivityRunningState.Done, DateTime.UtcNow.AddSeconds(-75), 1, 1, "/Root/Path1"), // 0 - RegisterActivity(IndexingActivityType.AddDocument, IndexingActivityRunningState.Done, DateTime.UtcNow.AddSeconds(-65), 2, 2, "/Root/Path2"), // 1 - RegisterActivity(IndexingActivityType.AddDocument, IndexingActivityRunningState.Done, DateTime.UtcNow.AddSeconds(-55), 3, 3, "/Root/Path3"), // 2 - RegisterActivity(IndexingActivityType.AddDocument, IndexingActivityRunningState.Done, DateTime.UtcNow, 4, 4, "/Root/Path4"), // 3 - - RegisterActivity(IndexingActivityType.AddDocument, IndexingActivityRunningState.Running, DateTime.UtcNow.AddSeconds(-75), 5, 5, "/Root/Path5"), // 4 - RegisterActivity(IndexingActivityType.AddDocument, IndexingActivityRunningState.Running, DateTime.UtcNow.AddSeconds(-65), 6, 6, "/Root/Path6"), // 5 - RegisterActivity(IndexingActivityType.AddDocument, IndexingActivityRunningState.Running, DateTime.UtcNow.AddSeconds(-55), 7, 7, "/Root/Path7"), // 6 - RegisterActivity(IndexingActivityType.AddDocument, IndexingActivityRunningState.Running, DateTime.UtcNow, 8, 8, "/Root/Path8"), // 7 - - RegisterActivity(IndexingActivityType.AddDocument, IndexingActivityRunningState.Waiting, DateTime.UtcNow.AddSeconds(-75), 10, 10, "/Root/Path10"), // 8 - RegisterActivity(IndexingActivityType.AddDocument, IndexingActivityRunningState.Waiting, DateTime.UtcNow.AddSeconds(-65), 11, 11, "/Root/Path11"), // 9 - RegisterActivity(IndexingActivityType.AddDocument, IndexingActivityRunningState.Waiting, DateTime.UtcNow.AddSeconds(-55), 12, 12, "/Root/Path12"), // 10 - RegisterActivity(IndexingActivityType.AddDocument, IndexingActivityRunningState.Waiting, DateTime.UtcNow, 13, 13, "/Root/Path13"), // 11 - }; - - var allocated = DataProvider.Current.LoadExecutableIndexingActivities(new IndexingActivityFactory(), 10, 60); - - Assert.AreEqual(6, allocated.Length); - Assert.AreEqual(start[4].Id, allocated[0].Id); - Assert.AreEqual(start[5].Id, allocated[1].Id); - Assert.AreEqual(start[8].Id, allocated[2].Id); - Assert.AreEqual(start[9].Id, allocated[3].Id); - Assert.AreEqual(start[10].Id, allocated[4].Id); - Assert.AreEqual(start[11].Id, allocated[5].Id); - } - } - [TestMethod, TestCategory("IR")] - public void Indexing_Centralized_InMemory_Allocate07_MaxRecords() - { - using (new Tests.Tools.DataProviderSwindler(new InMemoryDataProvider())) - { - var start = new IIndexingActivity[15]; - for (int i = 1; i <= start.Length; i++) - { - start[i - 1] = RegisterActivity(IndexingActivityType.AddDocument, IndexingActivityRunningState.Waiting, i, i, $"/Root/Path0{i}"); - } - - var allocated = DataProvider.Current.LoadExecutableIndexingActivities(new IndexingActivityFactory(), 10, 60); - - Assert.AreEqual(10, allocated.Length); - for (var i = 0; i < 10; i++) - Assert.AreEqual(start[i].Id, allocated[i].Id); - } - } - [TestMethod, TestCategory("IR")] - public void Indexing_Centralized_InMemory_Allocate08_StateUpdated() - { - using (new Tests.Tools.DataProviderSwindler(new InMemoryDataProvider())) - { - var start = new[] - { - RegisterActivity(IndexingActivityType.AddDocument, IndexingActivityRunningState.Waiting, 1, 1, "/Root/Path1"), - RegisterActivity(IndexingActivityType.UpdateDocument, IndexingActivityRunningState.Waiting, 1, 1, "/Root/Path1"), - RegisterActivity(IndexingActivityType.AddDocument, IndexingActivityRunningState.Waiting, 2, 2, "/Root/Path2"), - RegisterActivity(IndexingActivityType.UpdateDocument, IndexingActivityRunningState.Waiting, 2, 2, "/Root/Path2"), - }; - - var allocated = DataProvider.Current.LoadExecutableIndexingActivities(new IndexingActivityFactory(), 10, 60); - - Assert.AreEqual(2, allocated.Length); - Assert.AreEqual(start[0].Id, allocated[0].Id); - Assert.AreEqual(start[2].Id, allocated[1].Id); - Assert.AreEqual(IndexingActivityRunningState.Running, allocated[0].RunningState); - Assert.AreEqual(IndexingActivityRunningState.Running, allocated[1].RunningState); - } - } - - [TestMethod, TestCategory("IR")] - public void Indexing_Centralized_InMemory_AllocateAndState() - { - using (new Tests.Tools.DataProviderSwindler(new InMemoryDataProvider())) - { - var start = new[] - { - RegisterActivity(IndexingActivityType.AddDocument, IndexingActivityRunningState.Done, 1, 1, "/Root/Path1"), - RegisterActivity(IndexingActivityType.UpdateDocument, IndexingActivityRunningState.Waiting, 1, 1, "/Root/Path1"), - RegisterActivity(IndexingActivityType.AddDocument, IndexingActivityRunningState.Running, 2, 2, "/Root/Path2"), - RegisterActivity(IndexingActivityType.UpdateDocument, IndexingActivityRunningState.Waiting, 2, 2, "/Root/Path2"), - RegisterActivity(IndexingActivityType.AddDocument, IndexingActivityRunningState.Waiting, 3, 3, "/Root/Path3"), - RegisterActivity(IndexingActivityType.UpdateDocument, IndexingActivityRunningState.Waiting, 3, 3, "/Root/Path3"), - }; - - var waitingIds = new[] { start[0].Id, start[2].Id }; - - var allocated = DataProvider.Current.LoadExecutableIndexingActivities(new IndexingActivityFactory(), 10, 60, waitingIds, out int[] finishetIds); - - Assert.AreEqual(1, finishetIds.Length); - Assert.AreEqual(start[0].Id, finishetIds[0]); - - Assert.AreEqual(2, allocated.Length); - Assert.AreEqual(start[1].Id, allocated[0].Id); - Assert.AreEqual(start[4].Id, allocated[1].Id); - Assert.AreEqual(IndexingActivityRunningState.Running, allocated[0].RunningState); - Assert.AreEqual(IndexingActivityRunningState.Running, allocated[1].RunningState); - } - } - [TestMethod, TestCategory("IR")] - public void Indexing_Centralized_InMemory_RefreshLock() - { - using (new Tests.Tools.DataProviderSwindler(new InMemoryDataProvider())) - { - var now = DateTime.UtcNow; - var time1 = now.AddSeconds(-60 * 6); - var time2 = now.AddSeconds(-60 * 5); - var time3 = now.AddSeconds(-60 * 4); - var time4 = now.AddSeconds(-60 * 3); - var start = new[] - { - RegisterActivity(IndexingActivityType.Rebuild, IndexingActivityRunningState.Waiting, time1, 1, 1, "/Root/Path1"), - RegisterActivity(IndexingActivityType.Rebuild, IndexingActivityRunningState.Waiting, time2, 2, 2, "/Root/Path2"), - RegisterActivity(IndexingActivityType.Rebuild, IndexingActivityRunningState.Waiting, time3, 3, 3, "/Root/Path3"), - RegisterActivity(IndexingActivityType.Rebuild, IndexingActivityRunningState.Waiting, time4, 4, 4, "/Root/Path4"), - }; - var startIds = start.Select(x => x.Id).ToArray(); - - var waitingIds = new[] { start[1].Id, start[2].Id }; - DataProvider.Current.RefreshIndexingActivityLockTime(waitingIds); - - var activities = DataProvider.Current.LoadIndexingActivities(startIds, false, IndexingActivityFactory.Instance); - - Assert.AreEqual(4, activities.Length); - - Assert.IsTrue(time1 == activities[0].LockTime); - Assert.IsTrue(now <= activities[1].LockTime); - Assert.IsTrue(now <= activities[2].LockTime); - Assert.IsTrue(time4 == activities[3].LockTime); - } - } - [TestMethod, TestCategory("IR")] - public void Indexing_Centralized_InMemory_DeleteFinished() - { - using (new Tests.Tools.DataProviderSwindler(new InMemoryDataProvider())) - { - var start = new[] - { - RegisterActivity(IndexingActivityType.AddDocument, IndexingActivityRunningState.Done, 1, 1, "/Root/Path1"), - RegisterActivity(IndexingActivityType.AddDocument, IndexingActivityRunningState.Done, 2, 2, "/Root/Path2"), - RegisterActivity(IndexingActivityType.AddDocument, IndexingActivityRunningState.Running, 3, 3, "/Root/Path3"), - RegisterActivity(IndexingActivityType.UpdateDocument, IndexingActivityRunningState.Waiting, 3, 3, "/Root/Path3"), - RegisterActivity(IndexingActivityType.AddDocument, IndexingActivityRunningState.Done, 4, 4, "/Root/Path4"), - RegisterActivity(IndexingActivityType.AddDocument, IndexingActivityRunningState.Waiting, 5, 5, "/Root/Path5"), - }; - - DataProvider.Current.DeleteFinishedIndexingActivities(); - - var loaded = DataProvider.Current.LoadIndexingActivities(0, int.MaxValue, 9999, false, IndexingActivityFactory.Instance); - - Assert.AreEqual(3, loaded.Length); - - Assert.AreEqual(start[2].Id, loaded[0].Id); - Assert.AreEqual(start[3].Id, loaded[1].Id); - Assert.AreEqual(start[5].Id, loaded[2].Id); - } - } - - /* ====================================================================================== */ - - private IIndexingActivity RegisterActivity(IndexingActivityType type, IndexingActivityRunningState state, int nodeId, int versionId, string path) - { - IndexingActivityBase activity; - if (type == IndexingActivityType.AddTree || type == IndexingActivityType.RemoveTree) - activity = CreateTreeActivity(type, path, nodeId, null); - else - activity = CreateActivity(type, path, nodeId, versionId, 9999, null); - activity.RunningState = state; - - DataProvider.Current.RegisterIndexingActivity(activity); - - return activity; - } - private IIndexingActivity RegisterActivity(IndexingActivityType type, IndexingActivityRunningState state, DateTime lockTime, int nodeId, int versionId, string path) - { - IndexingActivityBase activity; - if (type == IndexingActivityType.AddTree || type == IndexingActivityType.RemoveTree) - activity = CreateTreeActivity(type, path, nodeId, null); - else - activity = CreateActivity(type, path, nodeId, versionId, 9999, null); - - activity.RunningState = state; - activity.LockTime = lockTime; - - DataProvider.Current.RegisterIndexingActivity(activity); - - return activity; - } - - private static IndexingActivityBase CreateActivity(IndexingActivityType type, string path, int nodeId, int versionId, long versionTimestamp, IndexDocumentData indexDocumentData) - { - var populatorAcc = new PrivateType(typeof(DocumentPopulator)); - var result = populatorAcc.InvokeStatic("CreateActivity", type, path, nodeId, versionId, versionTimestamp, null, indexDocumentData); - return (IndexingActivityBase)result; - } - private static IndexingActivityBase CreateTreeActivity(IndexingActivityType type, string path, int nodeId, IndexDocumentData indexDocumentData) - { - var populatorAcc = new PrivateType(typeof(DocumentPopulator)); - var result = populatorAcc.InvokeStatic("CreateTreeActivity", type, path, nodeId, indexDocumentData); - return (IndexingActivityBase)result; - } - } -} diff --git a/src/Tests/SenseNet.Search.IntegrationTests/CentralizedIndexingSqlTests.cs b/src/Tests/SenseNet.Search.IntegrationTests/CentralizedIndexingSqlTests.cs deleted file mode 100644 index a9653cb82..000000000 --- a/src/Tests/SenseNet.Search.IntegrationTests/CentralizedIndexingSqlTests.cs +++ /dev/null @@ -1,618 +0,0 @@ -using System; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using SenseNet.ContentRepository.Storage.Data; -using System.Linq; -using System.Threading; -using SenseNet.ContentRepository.Search.Indexing; -using SenseNet.ContentRepository.Search.Indexing.Activities; -using SenseNet.Tests; - -namespace SenseNet.Search.IntegrationTests -{ - [TestClass] - public class CentralizedIndexingSqlTests : TestBase - { - private static string _connectionString = @"Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=sn7tests;Data Source=.\SQL2016"; - - [TestMethod, TestCategory("IR")] - public void Indexing_Centralized_Sql_RegisterAndReload() - { - var connectionStringBackup = Configuration.ConnectionStrings.ConnectionString; - Configuration.ConnectionStrings.ConnectionString = _connectionString; - try - { - CleanupIndexingActivitiesTable(); - - var lastActivityIdBefore = DataProvider.Current.GetLastIndexingActivityId(); - - var timeAtStart = DateTime.UtcNow; - - // avoid rounding errors: reloaded datetime can be less than timeAtStart - // if rounding in sql converts the input to smaller value. - Thread.Sleep(10); - - var activities = new[] - { - CreateActivity(IndexingActivityType.AddDocument, "/Root/42", 42, 42, 99999999, null), - CreateActivity(IndexingActivityType.UpdateDocument, "/Root/43", 43, 43, 99999999, null), - CreateTreeActivity(IndexingActivityType.AddTree, "/Root/44", 44, null), - CreateTreeActivity(IndexingActivityType.RemoveTree, "/Root/45", 45, null), - CreateActivity(IndexingActivityType.Rebuild, "/Root/46", 46, 46, 99999999, null), - }; - - foreach (var activity in activities) - DataProvider.Current.RegisterIndexingActivity(activity); - - // avoid rounding errors: reloaded datetime can be greater than timeAtEnd - // if rounding in sql converts the input to greater value. - Thread.Sleep(10); - - var timeAtEnd = DateTime.UtcNow; - - var lastActivityIdAfter = DataProvider.Current.GetLastIndexingActivityId(); - Assert.AreEqual(lastActivityIdBefore + 5, lastActivityIdAfter); - - var factory = new IndexingActivityFactory(); - - // ---- simulating system start - var unprocessedActivities = DataProvider.Current.LoadIndexingActivities(lastActivityIdBefore + 1, lastActivityIdAfter, 1000, true, factory); - Assert.AreEqual(5, unprocessedActivities.Length); - Assert.AreEqual( - $"{IndexingActivityType.AddDocument}, {IndexingActivityType.UpdateDocument}, {IndexingActivityType.AddTree}, {IndexingActivityType.RemoveTree}, {IndexingActivityType.Rebuild}", - string.Join(", ", unprocessedActivities.Select(x => x.ActivityType.ToString()).ToArray())); - Assert.AreEqual( - "42, 43, 44, 45, 46", - string.Join(", ", unprocessedActivities.Select(x => x.NodeId.ToString()).ToArray())); - Assert.AreEqual( - "42, 43, 0, 0, 46", - string.Join(", ", unprocessedActivities.Select(x => x.VersionId.ToString()).ToArray())); - Assert.AreEqual( - "/root/42, /root/43, /root/44, /root/45, /root/46", - string.Join(", ", unprocessedActivities.Select(x => x.Path))); - - for (int i = 0; i < unprocessedActivities.Length; i++) - { - Assert.AreEqual(lastActivityIdBefore + i + 1, unprocessedActivities[i].Id); - Assert.IsTrue(timeAtStart <= unprocessedActivities[i].CreationDate && unprocessedActivities[i].CreationDate <= timeAtEnd); - Assert.IsTrue(unprocessedActivities[i].IsUnprocessedActivity); - Assert.AreEqual(IndexingActivityRunningState.Waiting, unprocessedActivities[i].RunningState); - Assert.IsNull(unprocessedActivities[i].LockTime); - } - - // ---- simulating runtime maintenance - var loadedActivities = DataProvider.Current.LoadIndexingActivities(lastActivityIdBefore + 1, lastActivityIdAfter, 1000, false, factory); - Assert.AreEqual(5, loadedActivities.Length); - Assert.AreEqual( - $"{IndexingActivityType.AddDocument}, {IndexingActivityType.UpdateDocument}, {IndexingActivityType.AddTree}, {IndexingActivityType.RemoveTree}, {IndexingActivityType.Rebuild}", - string.Join(", ", loadedActivities.Select(x => x.ActivityType.ToString()).ToArray())); - Assert.AreEqual( - "42, 43, 44, 45, 46", - string.Join(", ", loadedActivities.Select(x => x.NodeId.ToString()).ToArray())); - Assert.AreEqual( - "42, 43, 0, 0, 46", - string.Join(", ", loadedActivities.Select(x => x.VersionId.ToString()).ToArray())); - Assert.AreEqual( - "/root/42, /root/43, /root/44, /root/45, /root/46", - string.Join(", ", loadedActivities.Select(x => x.Path))); - - for (int i = 0; i < loadedActivities.Length; i++) - { - Assert.AreEqual(lastActivityIdBefore + i + 1, loadedActivities[i].Id); - Assert.IsTrue(timeAtStart <= loadedActivities[i].CreationDate && loadedActivities[i].CreationDate <= timeAtEnd); - Assert.IsFalse(loadedActivities[i].IsUnprocessedActivity); - Assert.AreEqual(IndexingActivityRunningState.Waiting, unprocessedActivities[i].RunningState); - Assert.IsNull(unprocessedActivities[i].LockTime); - } - - var gaps = new[] { lastActivityIdBefore + 1, lastActivityIdBefore + 2 }; - // ---- simulating system start - var unprocessedActivitiesFromGaps = DataProvider.Current.LoadIndexingActivities(gaps, true, factory); - Assert.AreEqual( - $"{lastActivityIdBefore + 1}, {lastActivityIdBefore + 2}", - string.Join(", ", unprocessedActivitiesFromGaps.Select(x => x.Id.ToString()).ToArray())); - Assert.AreEqual( - "True, True", - string.Join(", ", unprocessedActivitiesFromGaps.Select(x => x.IsUnprocessedActivity.ToString()).ToArray())); - // ---- simulating runtime maintenance - var loadedActivitiesFromGaps = DataProvider.Current.LoadIndexingActivities(gaps, false, factory); - Assert.AreEqual( - $"{lastActivityIdBefore + 1}, {lastActivityIdBefore + 2}", - string.Join(", ", loadedActivitiesFromGaps.Select(x => x.Id.ToString()).ToArray())); - Assert.AreEqual( - "False, False", - string.Join(", ", loadedActivitiesFromGaps.Select(x => x.IsUnprocessedActivity.ToString()).ToArray())); - } - finally - { - Configuration.ConnectionStrings.ConnectionString = connectionStringBackup; - } - } - - [TestMethod, TestCategory("IR")] - public void Indexing_Centralized_Sql_UpdateStateToDone() - { - var connectionStringBackup = Configuration.ConnectionStrings.ConnectionString; - Configuration.ConnectionStrings.ConnectionString = _connectionString; - try - { - CleanupIndexingActivitiesTable(); - - var lastActivityIdBefore = DataProvider.Current.GetLastIndexingActivityId(); - DataProvider.Current.RegisterIndexingActivity( - CreateActivity( - IndexingActivityType.AddDocument, "/Root/Indexing_Centralized_Sql_UpdateStateToDone", 42, 42, 99999999, null)); - var lastActivityIdAfter = DataProvider.Current.GetLastIndexingActivityId(); - - var factory = new IndexingActivityFactory(); - var loadedActivities = DataProvider.Current.LoadIndexingActivities(lastActivityIdBefore + 1, lastActivityIdAfter, 1000, false, factory).ToArray(); - if (loadedActivities.Length != 1) - Assert.Inconclusive("Successful test needs one IndexingActivity."); - var loadedActivity = loadedActivities[0]; - if (loadedActivity == null) - Assert.Inconclusive("Successful test needs the existing IndexingActivity."); - if (loadedActivity.RunningState != IndexingActivityRunningState.Waiting) - Assert.Inconclusive("Successful test needs the requirement: ActivityState is IndexingActivityState.Waiting."); - - // action - DataProvider.Current.UpdateIndexingActivityRunningState(loadedActivity.Id, IndexingActivityRunningState.Done); - - // check - var lastActivityIdAfterUpdate = DataProvider.Current.GetLastIndexingActivityId(); - Assert.AreEqual(lastActivityIdAfter, lastActivityIdAfterUpdate); - - loadedActivity = DataProvider.Current.LoadIndexingActivities(lastActivityIdBefore + 1, lastActivityIdAfter, 1000, false, factory).First(); - Assert.AreEqual(IndexingActivityRunningState.Done, loadedActivity.RunningState); - } - finally - { - Configuration.ConnectionStrings.ConnectionString = connectionStringBackup; - } - } - - [TestMethod, TestCategory("IR")] - public void Indexing_Centralized_Sql_Allocate01_SelectWaiting() - { - var connectionStringBackup = Configuration.ConnectionStrings.ConnectionString; - Configuration.ConnectionStrings.ConnectionString = _connectionString; - try - { - CleanupIndexingActivitiesTable(); - var start = new[] - { - RegisterActivity(IndexingActivityType.AddDocument, IndexingActivityRunningState.Done, 1, 1, "/Root/Path1"), - RegisterActivity(IndexingActivityType.AddDocument, IndexingActivityRunningState.Running, 2, 2, "/Root/Path2"), - RegisterActivity(IndexingActivityType.AddDocument, IndexingActivityRunningState.Waiting, 3, 3, "/Root/Path3"), - }; - - var allocated = DataProvider.Current.LoadExecutableIndexingActivities(new IndexingActivityFactory(), 10, 60); - - Assert.AreEqual(1, allocated.Length); - Assert.AreEqual(start[2].Id, allocated[0].Id); - } - finally - { - Configuration.ConnectionStrings.ConnectionString = connectionStringBackup; - } - } - [TestMethod, TestCategory("IR")] - public void Indexing_Centralized_Sql_Allocate02_IdDependency() - { - var connectionStringBackup = Configuration.ConnectionStrings.ConnectionString; - Configuration.ConnectionStrings.ConnectionString = _connectionString; - try - { - CleanupIndexingActivitiesTable(); - var start = new[] - { - RegisterActivity(IndexingActivityType.AddDocument, IndexingActivityRunningState.Waiting, 1, 1, "/Root/Path1"), - RegisterActivity(IndexingActivityType.UpdateDocument, IndexingActivityRunningState.Waiting, 1, 1, "/Root/Path1"), - RegisterActivity(IndexingActivityType.UpdateDocument, IndexingActivityRunningState.Waiting, 1, 1, "/Root/Path1"), - }; - - var allocated = DataProvider.Current.LoadExecutableIndexingActivities(new IndexingActivityFactory(), 10, 60); - - Assert.AreEqual(1, allocated.Length); - Assert.AreEqual(start[0].Id, allocated[0].Id); - } - finally - { - Configuration.ConnectionStrings.ConnectionString = connectionStringBackup; - } - } - [TestMethod, TestCategory("IR")] - public void Indexing_Centralized_Sql_Allocate02_IdDependency_VersionId0() - { - var connectionStringBackup = Configuration.ConnectionStrings.ConnectionString; - Configuration.ConnectionStrings.ConnectionString = _connectionString; - try - { - CleanupIndexingActivitiesTable(); - var start = new[] - { - RegisterActivity(IndexingActivityType.Rebuild, IndexingActivityRunningState.Waiting, 1, 0, "/Root/Path1"), - RegisterActivity(IndexingActivityType.Rebuild, IndexingActivityRunningState.Waiting, 2, 0, "/Root/Path2"), - RegisterActivity(IndexingActivityType.Rebuild, IndexingActivityRunningState.Waiting, 3, 0, "/Root/Path3"), - }; - - var allocated = DataProvider.Current.LoadExecutableIndexingActivities(new IndexingActivityFactory(), 10, 60); - - Assert.AreEqual(3, allocated.Length); - Assert.AreEqual(start[0].Id, allocated[0].Id); - Assert.AreEqual(start[1].Id, allocated[1].Id); - Assert.AreEqual(start[2].Id, allocated[2].Id); - } - finally - { - Configuration.ConnectionStrings.ConnectionString = connectionStringBackup; - } - } - [TestMethod, TestCategory("IR")] - public void Indexing_Centralized_Sql_Allocate03_InactiveDependency() - { - var connectionStringBackup = Configuration.ConnectionStrings.ConnectionString; - Configuration.ConnectionStrings.ConnectionString = _connectionString; - try - { - CleanupIndexingActivitiesTable(); - var start = new[] - { - RegisterActivity(IndexingActivityType.AddDocument, IndexingActivityRunningState.Done, 1, 1, "/Root/Path1"), - RegisterActivity(IndexingActivityType.AddDocument, IndexingActivityRunningState.Done, 2, 2, "/Root/Path2"), - RegisterActivity(IndexingActivityType.UpdateDocument, IndexingActivityRunningState.Waiting, 2, 2, "/Root/Path2"), - RegisterActivity(IndexingActivityType.UpdateDocument, IndexingActivityRunningState.Waiting, 2, 2, "/Root/Path2"), - RegisterActivity(IndexingActivityType.UpdateDocument, IndexingActivityRunningState.Waiting, 2, 2, "/Root/Path2"), - }; - - var allocated = DataProvider.Current.LoadExecutableIndexingActivities(new IndexingActivityFactory(), 10, 60); - - Assert.AreEqual(1, allocated.Length); - Assert.AreEqual(start[2].Id, allocated[0].Id); - } - finally - { - Configuration.ConnectionStrings.ConnectionString = connectionStringBackup; - } - } - [TestMethod, TestCategory("IR")] - public void Indexing_Centralized_Sql_Allocate04_SelectMore() - { - var connectionStringBackup = Configuration.ConnectionStrings.ConnectionString; - Configuration.ConnectionStrings.ConnectionString = _connectionString; - try - { - CleanupIndexingActivitiesTable(); - var start = new[] - { - RegisterActivity(IndexingActivityType.AddDocument, IndexingActivityRunningState.Done, 1, 1, "/Root/Path1"), // 0 - RegisterActivity(IndexingActivityType.AddDocument, IndexingActivityRunningState.Done, 2, 2, "/Root/Path2"), // 1 - RegisterActivity(IndexingActivityType.UpdateDocument, IndexingActivityRunningState.Waiting, 2, 2, "/Root/Path2"), // 2 - RegisterActivity(IndexingActivityType.UpdateDocument, IndexingActivityRunningState.Waiting, 2, 2, "/Root/Path2"), // 3 - RegisterActivity(IndexingActivityType.UpdateDocument, IndexingActivityRunningState.Waiting, 2, 2, "/Root/Path2"), // 4 - RegisterActivity(IndexingActivityType.AddDocument, IndexingActivityRunningState.Waiting, 3, 3, "/Root/Path3"), // 5 - RegisterActivity(IndexingActivityType.UpdateDocument, IndexingActivityRunningState.Waiting, 3, 3, "/Root/Path3"), // 6 - RegisterActivity(IndexingActivityType.AddDocument, IndexingActivityRunningState.Waiting, 4, 4, "/Root/Path4"), // 7 - RegisterActivity(IndexingActivityType.UpdateDocument, IndexingActivityRunningState.Waiting, 4, 4, "/Root/Path4"), // 8 - }; - - var allocated = DataProvider.Current.LoadExecutableIndexingActivities(new IndexingActivityFactory(), 10, 60); - - Assert.AreEqual(3, allocated.Length); - Assert.AreEqual(start[2].Id, allocated[0].Id); - Assert.AreEqual(start[5].Id, allocated[1].Id); - Assert.AreEqual(start[7].Id, allocated[2].Id); - } - finally - { - Configuration.ConnectionStrings.ConnectionString = connectionStringBackup; - } - } - [TestMethod, TestCategory("IR")] - public void Indexing_Centralized_Sql_Allocate05_PathDependency() - { - var connectionStringBackup = Configuration.ConnectionStrings.ConnectionString; - Configuration.ConnectionStrings.ConnectionString = _connectionString; - try - { - CleanupIndexingActivitiesTable(); - var start = new[] - { - RegisterActivity(IndexingActivityType.AddTree, IndexingActivityRunningState.Waiting, 1, 1, "/Root/Path1"), // 0 - RegisterActivity(IndexingActivityType.AddDocument, IndexingActivityRunningState.Waiting, 2, 2, "/Root/Path2"), // 1 - RegisterActivity(IndexingActivityType.UpdateDocument, IndexingActivityRunningState.Waiting, 3, 3, "/Root/Path1/aaa"), // 2 - RegisterActivity(IndexingActivityType.UpdateDocument, IndexingActivityRunningState.Waiting, 4, 4, "/Root/Path1/bbb"), // 3 - RegisterActivity(IndexingActivityType.UpdateDocument, IndexingActivityRunningState.Waiting, 2, 2, "/Root/Path2"), // 4 - RegisterActivity(IndexingActivityType.AddDocument, IndexingActivityRunningState.Waiting, 5, 5, "/Root/Path3/xxx"), // 5 - RegisterActivity(IndexingActivityType.AddTree, IndexingActivityRunningState.Waiting, 6, 6, "/Root/Path3"), // 6 - RegisterActivity(IndexingActivityType.AddDocument, IndexingActivityRunningState.Waiting, 7, 7, "/Root/Path4"), // 7 - }; - - var allocated = DataProvider.Current.LoadExecutableIndexingActivities(new IndexingActivityFactory(), 10, 60); - - Assert.AreEqual(4, allocated.Length); - Assert.AreEqual(start[0].Id, allocated[0].Id); - Assert.AreEqual(start[1].Id, allocated[1].Id); - Assert.AreEqual(start[5].Id, allocated[2].Id); - Assert.AreEqual(start[7].Id, allocated[3].Id); - } - finally - { - Configuration.ConnectionStrings.ConnectionString = connectionStringBackup; - } - } - [TestMethod, TestCategory("IR")] - public void Indexing_Centralized_Sql_Allocate06_Timeout() - { - var connectionStringBackup = Configuration.ConnectionStrings.ConnectionString; - Configuration.ConnectionStrings.ConnectionString = _connectionString; - try - { - CleanupIndexingActivitiesTable(); - var start = new[] - { - RegisterActivity(IndexingActivityType.AddDocument, IndexingActivityRunningState.Done, DateTime.UtcNow.AddSeconds(-75), 1, 1, "/Root/Path1"), // 0 - RegisterActivity(IndexingActivityType.AddDocument, IndexingActivityRunningState.Done, DateTime.UtcNow.AddSeconds(-65), 2, 2, "/Root/Path2"), // 1 - RegisterActivity(IndexingActivityType.AddDocument, IndexingActivityRunningState.Done, DateTime.UtcNow.AddSeconds(-55), 3, 3, "/Root/Path3"), // 2 - RegisterActivity(IndexingActivityType.AddDocument, IndexingActivityRunningState.Done, DateTime.UtcNow, 4, 4, "/Root/Path4"), // 3 - - RegisterActivity(IndexingActivityType.AddDocument, IndexingActivityRunningState.Running, DateTime.UtcNow.AddSeconds(-75), 5, 5, "/Root/Path5"), // 4 - RegisterActivity(IndexingActivityType.AddDocument, IndexingActivityRunningState.Running, DateTime.UtcNow.AddSeconds(-65), 6, 6, "/Root/Path6"), // 5 - RegisterActivity(IndexingActivityType.AddDocument, IndexingActivityRunningState.Running, DateTime.UtcNow.AddSeconds(-55), 7, 7, "/Root/Path7"), // 6 - RegisterActivity(IndexingActivityType.AddDocument, IndexingActivityRunningState.Running, DateTime.UtcNow, 8, 8, "/Root/Path8"), // 7 - - RegisterActivity(IndexingActivityType.AddDocument, IndexingActivityRunningState.Waiting, DateTime.UtcNow.AddSeconds(-75), 10, 10, "/Root/Path10"), // 8 - RegisterActivity(IndexingActivityType.AddDocument, IndexingActivityRunningState.Waiting, DateTime.UtcNow.AddSeconds(-65), 11, 11, "/Root/Path11"), // 9 - RegisterActivity(IndexingActivityType.AddDocument, IndexingActivityRunningState.Waiting, DateTime.UtcNow.AddSeconds(-55), 12, 12, "/Root/Path12"), // 10 - RegisterActivity(IndexingActivityType.AddDocument, IndexingActivityRunningState.Waiting, DateTime.UtcNow, 13, 13, "/Root/Path13"), // 11 - }; - - var allocated = DataProvider.Current.LoadExecutableIndexingActivities(new IndexingActivityFactory(), 10, 60); - - Assert.AreEqual(6, allocated.Length); - Assert.AreEqual(start[4].Id, allocated[0].Id); - Assert.AreEqual(start[5].Id, allocated[1].Id); - Assert.AreEqual(start[8].Id, allocated[2].Id); - Assert.AreEqual(start[9].Id, allocated[3].Id); - Assert.AreEqual(start[10].Id, allocated[4].Id); - Assert.AreEqual(start[11].Id, allocated[5].Id); - } - finally - { - Configuration.ConnectionStrings.ConnectionString = connectionStringBackup; - } - } - [TestMethod, TestCategory("IR")] - public void Indexing_Centralized_Sql_Allocate07_MaxRecords() - { - var connectionStringBackup = Configuration.ConnectionStrings.ConnectionString; - Configuration.ConnectionStrings.ConnectionString = _connectionString; - try - { - CleanupIndexingActivitiesTable(); - var start = new IIndexingActivity[15]; - for (int i = 1; i <= start.Length; i++) - { - start[i - 1] = RegisterActivity(IndexingActivityType.AddDocument, IndexingActivityRunningState.Waiting, i, i, $"/Root/Path0{i}"); - } - - var allocated = DataProvider.Current.LoadExecutableIndexingActivities(new IndexingActivityFactory(), 10, 60); - - Assert.AreEqual(10, allocated.Length); - for (var i = 0; i < 10; i++) - Assert.AreEqual(start[i].Id, allocated[i].Id); - } - finally - { - Configuration.ConnectionStrings.ConnectionString = connectionStringBackup; - } - } - [TestMethod, TestCategory("IR")] - public void Indexing_Centralized_Sql_Allocate08_StateUpdated() - { - var connectionStringBackup = Configuration.ConnectionStrings.ConnectionString; - Configuration.ConnectionStrings.ConnectionString = _connectionString; - try - { - CleanupIndexingActivitiesTable(); - var start = new[] - { - RegisterActivity(IndexingActivityType.AddDocument, IndexingActivityRunningState.Waiting, 1, 1, "/Root/Path1"), - RegisterActivity(IndexingActivityType.UpdateDocument, IndexingActivityRunningState.Waiting, 1, 1, "/Root/Path1"), - RegisterActivity(IndexingActivityType.AddDocument, IndexingActivityRunningState.Waiting, 2, 2, "/Root/Path2"), - RegisterActivity(IndexingActivityType.UpdateDocument, IndexingActivityRunningState.Waiting, 2, 2, "/Root/Path2"), - }; - - var allocated = DataProvider.Current.LoadExecutableIndexingActivities(new IndexingActivityFactory(), 10, 60); - - Assert.AreEqual(2, allocated.Length); - Assert.AreEqual(start[0].Id, allocated[0].Id); - Assert.AreEqual(start[2].Id, allocated[1].Id); - Assert.AreEqual(IndexingActivityRunningState.Running, allocated[0].RunningState); - Assert.AreEqual(IndexingActivityRunningState.Running, allocated[1].RunningState); - } - finally - { - Configuration.ConnectionStrings.ConnectionString = connectionStringBackup; - } - } - - [TestMethod, TestCategory("IR")] - public void Indexing_Centralized_Sql_AllocateAndState() - { - var connectionStringBackup = Configuration.ConnectionStrings.ConnectionString; - Configuration.ConnectionStrings.ConnectionString = _connectionString; - try - { - CleanupIndexingActivitiesTable(); - - var start = new[] - { - RegisterActivity(IndexingActivityType.AddDocument, IndexingActivityRunningState.Done, 1, 1, "/Root/Path1"), - RegisterActivity(IndexingActivityType.UpdateDocument, IndexingActivityRunningState.Waiting, 1, 1, "/Root/Path1"), - RegisterActivity(IndexingActivityType.AddDocument, IndexingActivityRunningState.Running, 2, 2, "/Root/Path2"), - RegisterActivity(IndexingActivityType.UpdateDocument, IndexingActivityRunningState.Waiting, 2, 2, "/Root/Path2"), - RegisterActivity(IndexingActivityType.AddDocument, IndexingActivityRunningState.Waiting, 3, 3, "/Root/Path3"), - RegisterActivity(IndexingActivityType.UpdateDocument, IndexingActivityRunningState.Waiting, 3, 3, "/Root/Path3"), - }; - - var waitingIds = new[] { start[0].Id, start[2].Id }; - - var allocated = DataProvider.Current.LoadExecutableIndexingActivities(new IndexingActivityFactory(), 10, 60, waitingIds, out int[] finishetIds); - - Assert.AreEqual(1, finishetIds.Length); - Assert.AreEqual(start[0].Id, finishetIds[0]); - - Assert.AreEqual(2, allocated.Length); - Assert.AreEqual(start[1].Id, allocated[0].Id); - Assert.AreEqual(start[4].Id, allocated[1].Id); - Assert.AreEqual(IndexingActivityRunningState.Running, allocated[0].RunningState); - Assert.AreEqual(IndexingActivityRunningState.Running, allocated[1].RunningState); - } - finally - { - Configuration.ConnectionStrings.ConnectionString = connectionStringBackup; - } - } - - [TestMethod, TestCategory("IR")] - public void Indexing_Centralized_Sql_RefreshLock() - { - var connectionStringBackup = Configuration.ConnectionStrings.ConnectionString; - Configuration.ConnectionStrings.ConnectionString = _connectionString; - try - { - CleanupIndexingActivitiesTable(); - - var now = DateTime.UtcNow; - var time1 = now.AddSeconds(-60 * 6); - var time2 = now.AddSeconds(-60 * 5); - var time3 = now.AddSeconds(-60 * 4); - var time4 = now.AddSeconds(-60 * 3); - var start = new[] - { - RegisterActivity(IndexingActivityType.Rebuild, IndexingActivityRunningState.Waiting, time1, 1, 1, "/Root/Path1"), - RegisterActivity(IndexingActivityType.Rebuild, IndexingActivityRunningState.Waiting, time2, 2, 2, "/Root/Path2"), - RegisterActivity(IndexingActivityType.Rebuild, IndexingActivityRunningState.Waiting, time3, 3, 3, "/Root/Path3"), - RegisterActivity(IndexingActivityType.Rebuild, IndexingActivityRunningState.Waiting, time4, 4, 4, "/Root/Path4"), - }; - var startIds = start.Select(x => x.Id).ToArray(); - - var waitingIds = new[] { start[1].Id, start[2].Id }; - DataProvider.Current.RefreshIndexingActivityLockTime(waitingIds); - - var activities = DataProvider.Current.LoadIndexingActivities(startIds, false, IndexingActivityFactory.Instance); - - Assert.AreEqual(4, activities.Length); - - // pay attention to difference due to rounding datetime in the database. - // ReSharper disable once PossibleInvalidOperationException - Assert.IsTrue(Math.Abs(((TimeSpan)(time1 - activities[0].LockTime)).Ticks) < TimeSpan.FromSeconds(0.01).Ticks); - Assert.IsTrue(now <= activities[1].LockTime); - Assert.IsTrue(now <= activities[2].LockTime); - // ReSharper disable once PossibleInvalidOperationException - Assert.IsTrue(Math.Abs(((TimeSpan)(time4 - activities[3].LockTime)).Ticks) < TimeSpan.FromSeconds(0.01).Ticks); - } - finally - { - Configuration.ConnectionStrings.ConnectionString = connectionStringBackup; - } - } - [TestMethod, TestCategory("IR")] - public void Indexing_Centralized_Sql_DeleteFinished() - { - var connectionStringBackup = Configuration.ConnectionStrings.ConnectionString; - Configuration.ConnectionStrings.ConnectionString = _connectionString; - try - { - CleanupIndexingActivitiesTable(); - - var start = new[] - { - RegisterActivity(IndexingActivityType.AddDocument, IndexingActivityRunningState.Done, 1, 1, "/Root/Path1", DateTime.UtcNow.AddHours(-1), DateTime.UtcNow.AddMinutes(-59)), - RegisterActivity(IndexingActivityType.AddDocument, IndexingActivityRunningState.Done, 2, 2, "/Root/Path2", DateTime.UtcNow.AddHours(-1), DateTime.UtcNow.AddMinutes(-59)), - RegisterActivity(IndexingActivityType.AddDocument, IndexingActivityRunningState.Running, 3, 3, "/Root/Path3"), - RegisterActivity(IndexingActivityType.UpdateDocument, IndexingActivityRunningState.Waiting, 3, 3, "/Root/Path3"), - RegisterActivity(IndexingActivityType.AddDocument, IndexingActivityRunningState.Done, 4, 4, "/Root/Path4", DateTime.UtcNow.AddHours(-1), DateTime.UtcNow.AddMinutes(-59)), - RegisterActivity(IndexingActivityType.AddDocument, IndexingActivityRunningState.Waiting, 5, 5, "/Root/Path5"), - }; - - DataProvider.Current.DeleteFinishedIndexingActivities(); - - var loaded = DataProvider.Current.LoadIndexingActivities(0, int.MaxValue, 9999, false, IndexingActivityFactory.Instance); - - Assert.AreEqual(3, loaded.Length); - - Assert.AreEqual(start[2].Id, loaded[0].Id); - Assert.AreEqual(start[3].Id, loaded[1].Id); - Assert.AreEqual(start[5].Id, loaded[2].Id); - } - finally - { - Configuration.ConnectionStrings.ConnectionString = connectionStringBackup; - } - } - /* ====================================================================================== */ - - public static void CleanupIndexingActivitiesTable() - { - var connectionStringBackup = Configuration.ConnectionStrings.ConnectionString; - Configuration.ConnectionStrings.ConnectionString = _connectionString; - try - { - DataProvider.Current.DeleteAllIndexingActivities(); - } - finally - { - Configuration.ConnectionStrings.ConnectionString = connectionStringBackup; - } - } - - private IIndexingActivity RegisterActivity(IndexingActivityType type, IndexingActivityRunningState state, - int nodeId, int versionId, string path, DateTime? creationDate = null, DateTime? lockTime = null) - { - IndexingActivityBase activity; - if (type == IndexingActivityType.AddTree || type == IndexingActivityType.RemoveTree) - activity = CreateTreeActivity(type, path, nodeId, null); - else - activity = CreateActivity(type, path, nodeId, versionId, 9999, null); - - activity.RunningState = state; - - if (creationDate.HasValue) - activity.CreationDate = creationDate.Value; - if (lockTime.HasValue) - activity.LockTime = lockTime; - - DataProvider.Current.RegisterIndexingActivity(activity); - - return activity; - } - private IIndexingActivity RegisterActivity(IndexingActivityType type, IndexingActivityRunningState state, DateTime lockTime, int nodeId, int versionId, string path) - { - IndexingActivityBase activity; - if (type == IndexingActivityType.AddTree || type == IndexingActivityType.RemoveTree) - activity = CreateTreeActivity(type, path, nodeId, null); - else - activity = CreateActivity(type, path, nodeId, versionId, 9999, null); - - activity.RunningState = state; - activity.LockTime = lockTime; - - DataProvider.Current.RegisterIndexingActivity(activity); - - return activity; - } - - private static IndexingActivityBase CreateActivity(IndexingActivityType type, string path, int nodeId, int versionId, long versionTimestamp, IndexDocumentData indexDocumentData) - { - var populatorAcc = new PrivateType(typeof(DocumentPopulator)); - var result = populatorAcc.InvokeStatic("CreateActivity", type, path, nodeId, versionId, versionTimestamp, null, indexDocumentData); - return (IndexingActivityBase)result; - } - private static IndexingActivityBase CreateTreeActivity(IndexingActivityType type, string path, int nodeId, IndexDocumentData indexDocumentData) - { - var populatorAcc = new PrivateType(typeof(DocumentPopulator)); - var result = populatorAcc.InvokeStatic("CreateTreeActivity", type, path, nodeId, indexDocumentData); - return (IndexingActivityBase)result; - } - } -} diff --git a/src/Tests/SenseNet.Search.IntegrationTests/FieldIndexHandlerTests.cs b/src/Tests/SenseNet.Search.IntegrationTests/FieldIndexHandlerTests.cs deleted file mode 100644 index 9462940f3..000000000 --- a/src/Tests/SenseNet.Search.IntegrationTests/FieldIndexHandlerTests.cs +++ /dev/null @@ -1,384 +0,0 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; -using SenseNet.Configuration; -using SenseNet.ContentRepository; -using SenseNet.ContentRepository.Fields; -using SenseNet.ContentRepository.Storage; -using SenseNet.Search.Indexing; -using SenseNet.Tests; -using SenseNet.Tests.Implementations; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace SenseNet.Search.IntegrationTests -{ - [TestClass] - public class FieldIndexHandlerTests : TestBase - { - private class IndexableField : IIndexableField - { - public string Name => "TestField"; - public bool IsInIndex => true; - public bool IsBinaryField => false; - private object _value; - - public IndexableField(object value) - { - _value = value; - } - - public object GetData() - { - return _value; - } - public IEnumerable GetIndexFields(out string textExtract) - { - throw new NotImplementedException(); - } - } - - [TestMethod, TestCategory("IR")] - public void FieldIndexHandler_BooleanIndexHandler() - { - var fieldValue = true; - var fieldValueObject = (object)fieldValue; - var snField = new IndexableField(fieldValueObject); - - var fieldIndexHandler = new BooleanIndexHandler(); - fieldIndexHandler.OwnerIndexingInfo = new TestPerfieldIndexingInfoBool(); - - var indexed = fieldIndexHandler.GetIndexFields(snField, out _); - var parsed = fieldIndexHandler.Parse("True"); - var termValue = fieldIndexHandler.ConvertToTermValue(fieldValue); - Assert.AreEqual(indexed.First().Type, parsed.Type); - Assert.AreEqual(parsed.Type, termValue.Type); - - var retrieved = fieldIndexHandler.GetBack("yes"); - Assert.AreEqual(fieldValue, retrieved); - } - [TestMethod, TestCategory("IR")] - public void FieldIndexHandler_IntegerIndexHandler() - { - var fieldValue = 42; - var fieldValueObject = (object)fieldValue; - var snField = new IndexableField(fieldValueObject); - - var fieldIndexHandler = new IntegerIndexHandler(); - fieldIndexHandler.OwnerIndexingInfo = new TestPerfieldIndexingInfoInt(); - - var indexed = fieldIndexHandler.GetIndexFields(snField, out _); - var parsed = fieldIndexHandler.Parse("42"); - var termValue = fieldIndexHandler.ConvertToTermValue(fieldValue); - Assert.AreEqual(indexed.First().Type, parsed.Type); - Assert.AreEqual(parsed.Type, termValue.Type); - - var retrieved = fieldIndexHandler.GetBack("42"); - Assert.AreEqual(fieldValue, retrieved); - } - [TestMethod, TestCategory("IR")] - public void FieldIndexHandler_NumberIndexHandler() - { - var fieldValue = Convert.ToDecimal(42L + int.MaxValue); - var fieldValueObject = (object)fieldValue; - var snField = new IndexableField(fieldValueObject); - - var fieldIndexHandler = new NumberIndexHandler(); - fieldIndexHandler.OwnerIndexingInfo = new TestPerfieldIndexingInfoLong(); - - var indexed = fieldIndexHandler.GetIndexFields(snField, out _); - var parsed = fieldIndexHandler.Parse(fieldValue.ToString()); - var termValue = fieldIndexHandler.ConvertToTermValue(fieldValue); - Assert.AreEqual(indexed.First().Type, parsed.Type); - Assert.AreEqual(parsed.Type, termValue.Type); - - var retrieved = fieldIndexHandler.GetBack(fieldValue.ToString()); - Assert.AreEqual(fieldValue, retrieved); - } - [TestMethod, TestCategory("IR")] - public void FieldIndexHandler_LongTextIndexHandler() - { - var fieldValue = "Long text."; - var fieldValueObject = (object)fieldValue; - var snField = new IndexableField(fieldValueObject); - - var fieldIndexHandler = new LongTextIndexHandler(); - fieldIndexHandler.OwnerIndexingInfo = new TestPerfieldIndexingInfoString(); - - var indexed = fieldIndexHandler.GetIndexFields(snField, out _); - var parsed = fieldIndexHandler.Parse(fieldValue.ToString()); - var termValue = fieldIndexHandler.ConvertToTermValue(fieldValue); - Assert.AreEqual(indexed.First().Type, parsed.Type); - Assert.AreEqual(parsed.Type, termValue.Type); - - // get back is not supported - } - [TestMethod, TestCategory("IR")] - public void FieldIndexHandler_InFolderIndexHandler() - { - var fieldValue = "/Root/A/B"; - var fieldValueObject = (object)fieldValue; - var snField = new IndexableField(fieldValueObject); - - var fieldIndexHandler = new InFolderIndexHandler(); - fieldIndexHandler.OwnerIndexingInfo = new TestPerfieldIndexingInfoString(); - - var indexed = fieldIndexHandler.GetIndexFields(snField, out _); - var parsed = fieldIndexHandler.Parse(fieldValue.ToString()); - var termValue = fieldIndexHandler.ConvertToTermValue(fieldValue); - Assert.AreEqual(indexed.First().Type, parsed.Type); - Assert.AreEqual(parsed.Type, termValue.Type); - - var retrieved = fieldIndexHandler.GetBack("/Root/A/B"); - Assert.AreEqual(fieldValue, retrieved); - } - [TestMethod, TestCategory("IR")] - public void FieldIndexHandler_InTreeIndexHandler() - { - var fieldValue = "/Root/A/B"; - var fieldValueObject = (object)fieldValue; - var snField = new IndexableField(fieldValueObject); - - var fieldIndexHandler = new InTreeIndexHandler(); - fieldIndexHandler.OwnerIndexingInfo = new TestPerfieldIndexingInfoString(); - - var indexed = fieldIndexHandler.GetIndexFields(snField, out _); - var parsed = fieldIndexHandler.Parse(fieldValue.ToString()); - var termValue = fieldIndexHandler.ConvertToTermValue(fieldValue); - Assert.AreEqual(indexed.First().Type, parsed.Type); - Assert.AreEqual(parsed.Type, termValue.Type); - - // get back is not supported - } - [TestMethod, TestCategory("IR")] - public void FieldIndexHandler_HyperLinkIndexHandler() - { - var fieldValue = new HyperLinkField.HyperlinkData("href", "text", "title", "target"); - var fieldValueObject = (object)fieldValue; - var snField = new IndexableField(fieldValueObject); - - var fieldIndexHandler = new HyperLinkIndexHandler(); - fieldIndexHandler.OwnerIndexingInfo = new TestPerfieldIndexingInfoString(); - - var indexed = fieldIndexHandler.GetIndexFields(snField, out _); - Assert.AreEqual(IndexValueType.StringArray, indexed.First().Type); - var parsed = fieldIndexHandler.Parse(fieldValue.ToString()); - Assert.AreEqual(IndexValueType.String, parsed.Type); - var termValue = fieldIndexHandler.ConvertToTermValue(fieldValue.ToString()); - Assert.AreEqual(parsed.Type, termValue.Type); - - // get back is not supported - } - [TestMethod, TestCategory("IR")] - public void FieldIndexHandler_PermissionChoiceIndexHandler() - { - var fieldValue = new[] { "href", "text", "title", "target" }; - var fieldValueObject = (object)fieldValue; - var snField = new IndexableField(fieldValueObject); - - var fieldIndexHandler = new PermissionChoiceIndexHandler(); - fieldIndexHandler.OwnerIndexingInfo = new TestPerfieldIndexingInfoString(); - - var indexed = fieldIndexHandler.GetIndexFields(snField, out _); - Assert.AreEqual(IndexValueType.StringArray, indexed.First().Type); - var parsed = fieldIndexHandler.Parse(fieldValue.ToString()); - Assert.AreEqual(IndexValueType.String, parsed.Type); - var termValue = fieldIndexHandler.ConvertToTermValue(fieldValue.ToString()); - Assert.AreEqual(parsed.Type, termValue.Type); - - // get back is not supported - } - [TestMethod, TestCategory("IR")] - public void FieldIndexHandler_TagIndexHandler() - { - var fieldValue = "Tag1,Tag2,Tag3"; - var fieldValueObject = (object)fieldValue; - var snField = new IndexableField(fieldValueObject); - - var fieldIndexHandler = new TagIndexHandler(); - fieldIndexHandler.OwnerIndexingInfo = new TestPerfieldIndexingInfoString(); - - var indexed = fieldIndexHandler.GetIndexFields(snField, out _); - Assert.AreEqual(IndexValueType.StringArray, indexed.First().Type); - var parsed = fieldIndexHandler.Parse(fieldValue.ToString()); - Assert.AreEqual(IndexValueType.String, parsed.Type); - var termValue = fieldIndexHandler.ConvertToTermValue(fieldValue.ToString()); - Assert.AreEqual(parsed.Type, termValue.Type); - - var retrieved = fieldIndexHandler.GetBack("tag1"); - Assert.AreEqual("tag1", retrieved); - } - - /* ===================================================================== tests with repo */ - - [TestMethod, TestCategory("IR")] - public void FieldIndexHandler_LowerStringIndexHandler() - { - Test(() => - { - var content = Content.Load(Identifiers.PortalRootId); - var contentName = content.Name; - var snField = content.Fields["Name"]; - - var fieldIndexHandler = new LowerStringIndexHandler(); - fieldIndexHandler.OwnerIndexingInfo = snField.FieldSetting.IndexingInfo; - - var indexed = fieldIndexHandler.GetIndexFields(snField, out _); - Assert.AreEqual(IndexValueType.String, indexed.First().Type); - var parsed = fieldIndexHandler.Parse(contentName); - Assert.AreEqual(IndexValueType.String, parsed.Type); - var termValue = fieldIndexHandler.ConvertToTermValue(contentName); - Assert.AreEqual(parsed.Type, termValue.Type); - - var retrieved = fieldIndexHandler.GetBack(contentName); - Assert.AreEqual(contentName, retrieved); - }); - } - [TestMethod, TestCategory("IR")] - public void FieldIndexHandler_DateTimeIndexHandler() - { - Test(() => - { - var content = Content.Load(Identifiers.PortalRootId); - var contentName = content.Name; - var snField = content.Fields["CreationDate"]; - - var fieldIndexHandler = new DateTimeIndexHandler(); - fieldIndexHandler.OwnerIndexingInfo = snField.FieldSetting.IndexingInfo; - - var indexed = fieldIndexHandler.GetIndexFields(snField, out _); - Assert.AreEqual(IndexValueType.DateTime, indexed.First().Type); - var parsed = fieldIndexHandler.Parse("2018-02-19 08:12:24"); - Assert.AreEqual(IndexValueType.DateTime, parsed.Type); - var termValue = fieldIndexHandler.ConvertToTermValue(DateTime.Now); - Assert.AreEqual(parsed.Type, termValue.Type); - - var now = DateTime.Now; - var retrieved = fieldIndexHandler.GetBack(now.Ticks.ToString()); - Assert.AreEqual(now, retrieved); - }); - } - [TestMethod, TestCategory("IR")] - public void FieldIndexHandler_TypeTreeIndexHandler() - { - Test(() => - { - var content = Content.Load(Identifiers.PortalRootId); - var contentName = content.Name; - var snField = content.Fields["Id"]; - - var fieldIndexHandler = new TypeTreeIndexHandler(); - fieldIndexHandler.OwnerIndexingInfo = snField.FieldSetting.IndexingInfo; - - var indexed = fieldIndexHandler.GetIndexFields(snField, out _); - Assert.AreEqual(IndexValueType.StringArray, indexed.First().Type); - var parsed = fieldIndexHandler.Parse("PortalRoot"); - Assert.AreEqual(IndexValueType.String, parsed.Type); - var termValue = fieldIndexHandler.ConvertToTermValue("PortalRoot"); - Assert.AreEqual(parsed.Type, termValue.Type); - - // get back is not supported - }); - } - [TestMethod, TestCategory("IR")] - public void FieldIndexHandler_ExclusiveTypeIndexHandler() - { - Test(() => - { - var content = Content.Load(Identifiers.PortalRootId); - var contentName = content.Name; - var snField = content.Fields["Id"]; - - var fieldIndexHandler = new ExclusiveTypeIndexHandler(); - fieldIndexHandler.OwnerIndexingInfo = snField.FieldSetting.IndexingInfo; - - var indexed = fieldIndexHandler.GetIndexFields(snField, out _); - Assert.AreEqual(IndexValueType.String, indexed.First().Type); - var parsed = fieldIndexHandler.Parse("PortalRoot"); - Assert.AreEqual(IndexValueType.String, parsed.Type); - var termValue = fieldIndexHandler.ConvertToTermValue("PortalRoot"); - Assert.AreEqual(parsed.Type, termValue.Type); - - // get back is not supported - }); - } - [TestMethod, TestCategory("IR")] - public void FieldIndexHandler_ReferenceIndexHandler() - { - Test(() => - { - var content = Content.Load(Identifiers.PortalRootId); - var contentName = content.Name; - var snField = content.Fields["CreatedBy"]; - - var fieldIndexHandler = new ReferenceIndexHandler(); - fieldIndexHandler.OwnerIndexingInfo = snField.FieldSetting.IndexingInfo; - - var indexed = fieldIndexHandler.GetIndexFields(snField, out _); - Assert.AreEqual(IndexValueType.Int, indexed.First().Type); - var parsed = fieldIndexHandler.Parse("2"); - Assert.AreEqual(IndexValueType.Int, parsed.Type); - var termValue = fieldIndexHandler.ConvertToTermValue(User.Administrator); - Assert.AreEqual(parsed.Type, termValue.Type); - - var retrieved = fieldIndexHandler.GetBack("42"); - Assert.AreEqual(42, retrieved); - }); - } - [TestMethod, TestCategory("IR")] - public void FieldIndexHandler_BinaryIndexHandler() - { - Test(() => - { - var binaryData = new BinaryData(); - binaryData.FileName = "file1.txt"; - binaryData.SetStream(RepositoryTools.GetStreamFromString("Stream data.")); - - var folder = new SystemFolder(Repository.Root) { Name = "Folder1" }; - folder.Save(); - var file = new File(folder) { Name = "file1.txt", Binary = binaryData }; - file.Save(); - var content = Content.Load(file.Id); - - var contentName = content.Name; - var snField = content.Fields["Binary"]; - - var fieldIndexHandler = new BinaryIndexHandler(); - fieldIndexHandler.OwnerIndexingInfo = snField.FieldSetting.IndexingInfo; - - var indexed = fieldIndexHandler.GetIndexFields(snField, out _); - Assert.AreEqual(IndexValueType.String, indexed.First().Type); - var parsed = fieldIndexHandler.Parse("Word1"); - Assert.AreEqual(IndexValueType.String, parsed.Type); - var termValue = fieldIndexHandler.ConvertToTermValue("Word1"); - Assert.AreEqual(parsed.Type, termValue.Type); - - // get back is not supported - }); - } - [TestMethod, TestCategory("IR")] - public void FieldIndexHandler_ChoiceIndexHandler() - { - Test(() => - { - var content = Content.Load(User.Administrator.Id); - var contentName = content.Name; - var snField = content.Fields["MaritalStatus"]; - - var fieldIndexHandler = new ChoiceIndexHandler(); - fieldIndexHandler.OwnerIndexingInfo = snField.FieldSetting.IndexingInfo; - - var indexed = fieldIndexHandler.GetIndexFields(snField, out _); - Assert.AreEqual(IndexValueType.StringArray, indexed.First().Type); - var parsed = fieldIndexHandler.Parse("married"); - Assert.AreEqual(IndexValueType.String, parsed.Type); - var termValue = fieldIndexHandler.ConvertToTermValue("married"); - Assert.AreEqual(parsed.Type, termValue.Type); - - // get back is not supported - }); - } - - } -} diff --git a/src/Tests/SenseNet.Search.IntegrationTests/Properties/AssemblyInfo.cs b/src/Tests/SenseNet.Search.IntegrationTests/Properties/AssemblyInfo.cs deleted file mode 100644 index d8f1ebce3..000000000 --- a/src/Tests/SenseNet.Search.IntegrationTests/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System.Reflection; -using System.Runtime.InteropServices; - -[assembly: AssemblyTitle("SenseNet.Search.IntegrationTests")] - -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("Sense/Net Inc.")] -[assembly: AssemblyCopyright("Copyright © Sense/Net Inc.")] -[assembly: AssemblyProduct("sensenet")] -[assembly: AssemblyTrademark("Sense/Net Inc.")] -[assembly: AssemblyCulture("")] -[assembly: AssemblyVersion("1.1.0.0")] -[assembly: AssemblyFileVersion("1.1.0.0")] -[assembly: AssemblyInformationalVersion("1.1.0.0")] - -[assembly: ComVisible(false)] -[assembly: Guid("a29cb53a-df6c-487c-9fdc-dc73a5cb2b13")] \ No newline at end of file diff --git a/src/Tests/SenseNet.Search.IntegrationTests/SenseNet.Search.IntegrationTests.csproj b/src/Tests/SenseNet.Search.IntegrationTests/SenseNet.Search.IntegrationTests.csproj deleted file mode 100644 index 30c5b52fe..000000000 --- a/src/Tests/SenseNet.Search.IntegrationTests/SenseNet.Search.IntegrationTests.csproj +++ /dev/null @@ -1,138 +0,0 @@ - - - - - Debug - AnyCPU - {11506B62-CDBB-40FB-AEDC-ABB393B3AC4D} - Library - Properties - SenseNet.Search.IntegrationTests - SenseNet.Search.IntegrationTests - v4.6.1 - 512 - {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - 15.0 - $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages - False - UnitTest - - - - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - - ..\..\packages\MSTest.TestFramework.1.2.0\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.dll - - - ..\..\packages\MSTest.TestFramework.1.2.0\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions.dll - - - ..\..\packages\Newtonsoft.Json.11.0.2\lib\net45\Newtonsoft.Json.dll - - - ..\..\packages\SenseNet.Security.3.0.0\lib\netstandard2.0\SenseNet.Security.dll - - - ..\..\packages\SenseNet.Tools.3.0.1\lib\netstandard2.0\SenseNet.Tools.dll - - - - - ..\..\packages\System.Configuration.ConfigurationManager.4.5.0\lib\net461\System.Configuration.ConfigurationManager.dll - - - - - - ..\..\packages\System.Data.SqlClient.4.5.1\lib\net461\System.Data.SqlClient.dll - - - ..\..\packages\System.Diagnostics.EventLog.4.5.0\lib\net461\System.Diagnostics.EventLog.dll - - - - - ..\..\packages\System.Security.AccessControl.4.5.0\lib\net461\System.Security.AccessControl.dll - - - ..\..\packages\System.Security.Permissions.4.5.0\lib\net461\System.Security.Permissions.dll - - - ..\..\packages\System.Security.Principal.Windows.4.5.0\lib\net461\System.Security.Principal.Windows.dll - - - - - - - - - - - - - - - Designer - - - - - {4e6722b5-ac95-494c-80a5-a4d80cc502b5} - SenseNet.BlobStorage - - - {a453e920-29c0-45cd-984c-0d8e3631b1e3} - SenseNet.Common - - - {786e6165-ca02-45a9-bf58-207a45d7d6df} - SenseNet.ContentRepository - - - {0279705b-779d-485d-86b9-f7ab3dd1f2c3} - SenseNet.Search - - - {b72529c8-feb1-49f5-b08b-56055b58f296} - SenseNet.Services - - - {5db4ddba-81f6-4d81-943a-18f3178b3355} - SenseNet.Storage - - - {A0909E8F-E039-4080-A259-676CFD38CCD1} - SenseNet.Tests - - - - - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - - - \ No newline at end of file diff --git a/src/Tests/SenseNet.Search.IntegrationTests/packages.config b/src/Tests/SenseNet.Search.IntegrationTests/packages.config deleted file mode 100644 index 26b29dc8d..000000000 --- a/src/Tests/SenseNet.Search.IntegrationTests/packages.config +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/Tests/SenseNet.Services.OData.Tests/SenseNet.Services.OData.Tests.csproj b/src/Tests/SenseNet.Services.OData.Tests/SenseNet.Services.OData.Tests.csproj index f911acec7..3f8babcd6 100644 --- a/src/Tests/SenseNet.Services.OData.Tests/SenseNet.Services.OData.Tests.csproj +++ b/src/Tests/SenseNet.Services.OData.Tests/SenseNet.Services.OData.Tests.csproj @@ -102,10 +102,6 @@ - - {4e6722b5-ac95-494c-80a5-a4d80cc502b5} - SenseNet.BlobStorage - {a453e920-29c0-45cd-984c-0d8e3631b1e3} SenseNet.Common diff --git a/src/Tests/SenseNet.Tests/Implementations/InMemoryBlobProvider.cs b/src/Tests/SenseNet.Tests/Implementations/InMemoryBlobProvider.cs index a02659bfe..4fb430c6e 100644 --- a/src/Tests/SenseNet.Tests/Implementations/InMemoryBlobProvider.cs +++ b/src/Tests/SenseNet.Tests/Implementations/InMemoryBlobProvider.cs @@ -30,11 +30,6 @@ public InMemoryBlobStorageMetaDataProvider(InMemoryDataProvider dataProvider) _dataProvider = dataProvider; } - public bool IsFilestreamEnabled() - { - return false; - } - public BlobStorageContext GetBlobStorageContext(int fileId, bool clearStream, int versionId, int propertyTypeId) { throw new NotImplementedException(); @@ -48,7 +43,7 @@ public Task GetBlobStorageContextAsync(int fileId, bool clea public void InsertBinaryProperty(IBlobProvider blobProvider, BinaryDataValue value, int versionId, int propertyTypeId, bool isNewNode) { var streamLength = value.Stream?.Length ?? 0; - var ctx = new BlobStorageContext(blobProvider) { VersionId = versionId, PropertyTypeId = propertyTypeId, FileId = 0, Length = streamLength, UseFileStream = false }; + var ctx = new BlobStorageContext(blobProvider) { VersionId = versionId, PropertyTypeId = propertyTypeId, FileId = 0, Length = streamLength }; // blob operation @@ -106,7 +101,6 @@ public void UpdateBinaryProperty(IBlobProvider blobProvider, BinaryDataValue val PropertyTypeId = 0, FileId = value.FileId, Length = streamLength, - UseFileStream = false }; blobProvider.Allocate(ctx); @@ -117,7 +111,7 @@ public void UpdateBinaryProperty(IBlobProvider blobProvider, BinaryDataValue val value.BlobProviderData = BlobStorageContext.SerializeBlobProviderData(ctx.BlobProviderData); } - var isRepositoryStream = value.Stream is RepositoryStream || value.Stream is SenseNetSqlFileStream; + var isRepositoryStream = value.Stream is RepositoryStream; var hasStream = isRepositoryStream || value.Stream is MemoryStream; if (!hasStream) // do not do any database operation if the stream is not modified @@ -177,7 +171,6 @@ public BinaryCacheEntity LoadBinaryCacheEntity(int versionId, int propertyTypeId PropertyTypeId = propertyTypeId, FileId = fileId, Length = length, - UseFileStream = false }; return new BinaryCacheEntity diff --git a/src/Tests/SenseNet.Tests/Implementations/InMemoryDataProvider.cs b/src/Tests/SenseNet.Tests/Implementations/InMemoryDataProvider.cs index fbc67511c..eb92c70bb 100644 --- a/src/Tests/SenseNet.Tests/Implementations/InMemoryDataProvider.cs +++ b/src/Tests/SenseNet.Tests/Implementations/InMemoryDataProvider.cs @@ -697,49 +697,6 @@ protected internal override bool IsCacheableText(string text) protected internal override BinaryCacheEntity LoadBinaryCacheEntity(int nodeVersionId, int propertyTypeId) { return BlobStorage.LoadBinaryCacheEntity(nodeVersionId, propertyTypeId); - - // SELECT F.Size, B.BinaryPropertyId, F.FileId, F.BlobProvider, F.BlobProviderData, - // CASE WHEN F.Size < 1048576 THEN F.Stream ELSE null END AS Stream - // FROM dbo.BinaryProperties B - // JOIN Files F ON B.FileId = F.FileId - // WHERE B.VersionId = @VersionId AND B.PropertyTypeId = @PropertyTypeId AND F.Staging IS NULL"; - - var binRec = _db.BinaryProperties - .FirstOrDefault(r => r.VersionId == nodeVersionId && r.PropertyTypeId == propertyTypeId); - if (binRec == null) - return null; - var fileRec = _db.Files.FirstOrDefault(f => f.FileId == binRec.FileId); - if (fileRec == null) - return null; - - var length = fileRec.Size; - var binaryPropertyId = binRec.BinaryPropertyId; - var fileId = binRec.FileId; - - // To avoid accessing to blob provider, read data here, else set rawData to null - byte[] rawData = fileRec.Stream; - - //TODO: partially implemented: IBlobProvider resolution always null. - IBlobProvider provider = null; //BlobStorageBase.GetProvider(null); - // ReSharper disable once ExpressionIsAlwaysNull - var context = new BlobStorageContext(provider) - { - VersionId = nodeVersionId, - PropertyTypeId = propertyTypeId, - FileId = fileId, - Length = length, - UseFileStream = false, - BlobProviderData = new BuiltinBlobProviderData {FileStreamData = null} - }; - - return new BinaryCacheEntity - { - Length = length, - RawData = rawData, - BinaryPropertyId = binaryPropertyId, - FileId = fileId, - Context = context - }; } #region NOT IMPLEMENTED diff --git a/src/Tests/SenseNet.Tests/SenseNet.Tests.csproj b/src/Tests/SenseNet.Tests/SenseNet.Tests.csproj index 3de9d6b27..801d4fee3 100644 --- a/src/Tests/SenseNet.Tests/SenseNet.Tests.csproj +++ b/src/Tests/SenseNet.Tests/SenseNet.Tests.csproj @@ -124,7 +124,7 @@ - {4e6722b5-ac95-494c-80a5-a4d80cc502b5} + {c250c071-6acd-42e0-9ffc-63283afb8c6c} SenseNet.BlobStorage diff --git a/tools/scripts/CreateNuGetPackages.ps1 b/tools/scripts/CreateNuGetPackages.ps1 index 0317642fe..ad1d7c8cb 100644 --- a/tools/scripts/CreateNuGetPackages.ps1 +++ b/tools/scripts/CreateNuGetPackages.ps1 @@ -5,7 +5,6 @@ $scriptsSourcePath = "$srcPath\Storage\Data\SqlClient\Scripts" # delete existing packages Remove-Item $PSScriptRoot\*.nupkg -nuget pack $srcPath\BlobStorage\SenseNet.BlobStorage.csproj -properties Configuration=Release -OutputDirectory $PSScriptRoot nuget pack $srcPath\Services\SenseNet.Services.nuspec -properties Configuration=Release -OutputDirectory $PSScriptRoot nuget pack $srcPath\Tests\SenseNet.Tests\SenseNet.Tests.nuspec -properties Configuration=Release -OutputDirectory $PSScriptRoot