Пример #1
0
		public void ImportData(Stream stream, SmugglerOptions options)
		{
			var sw = Stopwatch.StartNew();
			// Try to read the stream compressed, otherwise continue uncompressed.
			JsonTextReader jsonReader;
			try
			{
				var streamReader = new StreamReader(new GZipStream(stream, CompressionMode.Decompress));

				jsonReader = new JsonTextReader(streamReader);

				if (jsonReader.Read() == false)
					return;
			}
			catch (InvalidDataException)
			{
				stream.Seek(0, SeekOrigin.Begin);

				var streamReader = new StreamReader(stream);

				jsonReader = new JsonTextReader(streamReader);

				if (jsonReader.Read() == false)
					return;
			}

			if (jsonReader.TokenType != JsonToken.StartObject)
				throw new InvalidDataException("StartObject was expected");

			// should read indexes now
			if (jsonReader.Read() == false)
				return;
			if (jsonReader.TokenType != JsonToken.PropertyName)
				throw new InvalidDataException("PropertyName was expected");
			if (Equals("Indexes", jsonReader.Value) == false)
				throw new InvalidDataException("Indexes property was expected");
			if (jsonReader.Read() == false)
				return;
			if (jsonReader.TokenType != JsonToken.StartArray)
				throw new InvalidDataException("StartArray was expected");

			while (jsonReader.Read() && jsonReader.TokenType != JsonToken.EndArray)
			{
				var index = RavenJToken.ReadFrom(jsonReader);
				if (options.OperateOnTypes.HasFlag(ItemType.Indexes) == false)
					continue;
				var indexName = index.Value<string>("name");
				if (indexName.StartsWith("Raven/") || indexName.StartsWith("Temp/"))
					continue;

				var request = CreateRequest("indexes/" + indexName, "PUT");
				request.Write(index.Value<RavenJObject>("definition"));
				request.ExecuteRequest();
			}

			// should read documents now
			if (jsonReader.Read() == false)
				return;
			if (jsonReader.TokenType != JsonToken.PropertyName)
				throw new InvalidDataException("PropertyName was expected");
			if (Equals("Docs", jsonReader.Value) == false)
				throw new InvalidDataException("Docs property was expected");
			if (jsonReader.Read() == false)
				return;
			if (jsonReader.TokenType != JsonToken.StartArray)
				throw new InvalidDataException("StartArray was expected");
			var batch = new List<RavenJObject>();
			int totalCount = 0;
			while (jsonReader.Read() && jsonReader.TokenType != JsonToken.EndArray)
			{
				var document = (RavenJObject)RavenJToken.ReadFrom(jsonReader);
				if (options.OperateOnTypes.HasFlag(ItemType.Documents) == false)
					continue;
				if (options.MatchFilters(document) == false)
					continue;

				totalCount += 1;
				batch.Add(document);
				if (batch.Count >= 128)
					FlushBatch(batch);
			}
			FlushBatch(batch);

			var attachmentCount = 0;
			if (jsonReader.Read() == false || jsonReader.TokenType == JsonToken.EndObject)
				return;
			if (jsonReader.TokenType != JsonToken.PropertyName)
				throw new InvalidDataException("PropertyName was expected");
			if (Equals("Attachments", jsonReader.Value) == false)
				throw new InvalidDataException("Attachment property was expected");
			if (jsonReader.Read() == false)
				return;
			if (jsonReader.TokenType != JsonToken.StartArray)
				throw new InvalidDataException("StartArray was expected");
			while (jsonReader.Read() && jsonReader.TokenType != JsonToken.EndArray)
			{
				attachmentCount += 1;
				var item = RavenJToken.ReadFrom(jsonReader);
				if (options.OperateOnTypes.HasFlag(ItemType.Attachments) == false)
					continue;
				var attachmentExportInfo =
					new JsonSerializer
					{
						Converters = { new TrivialJsonToJsonJsonConverter() }
					}.Deserialize<AttachmentExportInfo>(new RavenJTokenReader(item));
				Console.WriteLine("Importing attachment {0}", attachmentExportInfo.Key);

				var request = CreateRequest("static/" + attachmentExportInfo.Key, "PUT");
				if (attachmentExportInfo.Metadata != null)
				{
					foreach (var header in attachmentExportInfo.Metadata)
					{
						request.WebRequest.Headers.Add(header.Key, StripQuotesIfNeeded(header.Value));
					}
				}

				request.Write(attachmentExportInfo.Data);
				request.ExecuteRequest();
			}
			Console.WriteLine("Imported {0:#,#;;0} documents and {1:#,#;;0} attachments in {2:#,#;;0} ms", totalCount, attachmentCount, sw.ElapsedMilliseconds);
		}
Пример #2
0
        private static async Task <Etag> ExportDocuments(DocumentStore exportStore, DocumentStore importStore, SmugglerOptions options, ServerSupportedFeatures exportStoreSupportedFeatures, int exportBatchSize, int importBatchSize)
        {
            var now = SystemTime.UtcNow;

            string lastEtag       = options.StartDocsEtag;
            var    totalCount     = 0;
            var    lastReport     = SystemTime.UtcNow;
            var    reportInterval = TimeSpan.FromSeconds(2);

            ShowProgress("Exporting Documents");

            var bulkInsertOperation = importStore.BulkInsert(null, new BulkInsertOptions
            {
                BatchSize         = importBatchSize,
                OverwriteExisting = true,
            });

            bulkInsertOperation.Report += text => ShowProgress(text);

            try
            {
                while (true)
                {
                    if (exportStoreSupportedFeatures.IsDocsStreamingSupported)
                    {
                        ShowProgress("Streaming documents from " + lastEtag);
                        using (var documentsEnumerator = await exportStore.AsyncDatabaseCommands.StreamDocsAsync(lastEtag))
                        {
                            while (await documentsEnumerator.MoveNextAsync())
                            {
                                var document = documentsEnumerator.Current;

                                if (!options.MatchFilters(document))
                                {
                                    continue;
                                }
                                if (options.ShouldExcludeExpired && options.ExcludeExpired(document, now))
                                {
                                    continue;
                                }

                                var metadata = document.Value <RavenJObject>("@metadata");
                                var id       = metadata.Value <string>("@id");
                                var etag     = Etag.Parse(metadata.Value <string>("@etag"));
                                document.Remove("@metadata");
                                bulkInsertOperation.Store(document, metadata, id);
                                totalCount++;

                                if (totalCount % 1000 == 0 || SystemTime.UtcNow - lastReport > reportInterval)
                                {
                                    ShowProgress("Exported {0} documents", totalCount);
                                    lastReport = SystemTime.UtcNow;
                                }

                                lastEtag = etag;
                            }
                        }
                    }
                    else
                    {
                        int retries = RetriesCount;
                        var originalRequestTimeout = exportStore.JsonRequestFactory.RequestTimeout;
                        var timeout = options.Timeout.Seconds;
                        if (timeout < 30)
                        {
                            timeout = 30;
                        }
                        try
                        {
                            var operationMetadata = new OperationMetadata(exportStore.Url, exportStore.Credentials, exportStore.ApiKey);

                            while (true)
                            {
                                try
                                {
                                    ShowProgress("Get documents from " + lastEtag);
                                    var documents = await((AsyncServerClient)exportStore.AsyncDatabaseCommands).GetDocumentsInternalAsync(null, lastEtag, exportBatchSize, operationMetadata);
                                    foreach (RavenJObject document in documents)
                                    {
                                        var metadata = document.Value <RavenJObject>("@metadata");
                                        var id       = metadata.Value <string>("@id");
                                        var etag     = Etag.Parse(metadata.Value <string>("@etag"));
                                        document.Remove("@metadata");
                                        metadata.Remove("@id");
                                        metadata.Remove("@etag");

                                        if (!options.MatchFilters(document))
                                        {
                                            continue;
                                        }
                                        if (options.ShouldExcludeExpired && options.ExcludeExpired(document, now))
                                        {
                                            continue;
                                        }

                                        bulkInsertOperation.Store(document, metadata, id);
                                        totalCount++;

                                        if (totalCount % 1000 == 0 || SystemTime.UtcNow - lastReport > reportInterval)
                                        {
                                            ShowProgress("Exported {0} documents", totalCount);
                                            lastReport = SystemTime.UtcNow;
                                        }
                                        lastEtag = etag;
                                    }
                                    break;
                                }
                                catch (Exception e)
                                {
                                    if (retries-- == 0)
                                    {
                                        throw;
                                    }
                                    exportStore.JsonRequestFactory.RequestTimeout = TimeSpan.FromSeconds(timeout *= 2);
                                    importStore.JsonRequestFactory.RequestTimeout = TimeSpan.FromSeconds(timeout *= 2);
                                    ShowProgress("Error reading from database, remaining attempts {0}, will retry. Error: {1}", retries, e);
                                }
                            }
                        }
                        finally
                        {
                            exportStore.JsonRequestFactory.RequestTimeout = originalRequestTimeout;
                        }
                    }

                    // In a case that we filter all the results, the formEtag hasn't updaed to the latest,
                    // but we still need to continue until we finish all the docs.
                    var databaseStatistics = await exportStore.AsyncDatabaseCommands.GetStatisticsAsync();

                    var lastEtagComparable = new ComparableByteArray(lastEtag);
                    if (lastEtagComparable.CompareTo(databaseStatistics.LastDocEtag) < 0)
                    {
                        lastEtag = EtagUtil.Increment(lastEtag, exportBatchSize);
                        ShowProgress("Got no results but didn't get to the last doc etag, trying from: {0}", lastEtag);
                        continue;
                    }

                    ShowProgress("Done with reading documents, total: {0}", totalCount);
                    return(lastEtag);
                }
            }
            finally
            {
                bulkInsertOperation.Dispose();
            }
        }
Пример #3
0
        public void ImportData(Stream stream, SmugglerOptions options)
        {
            EnsureDatabaseExists();

            var sw = Stopwatch.StartNew();
            // Try to read the stream compressed, otherwise continue uncompressed.
            JsonTextReader jsonReader;

            try
            {
                var streamReader = new StreamReader(new GZipStream(stream, CompressionMode.Decompress));

                jsonReader = new JsonTextReader(streamReader);

                if (jsonReader.Read() == false)
                {
                    return;
                }
            }
            catch (InvalidDataException)
            {
                stream.Seek(0, SeekOrigin.Begin);

                var streamReader = new StreamReader(stream);

                jsonReader = new JsonTextReader(streamReader);

                if (jsonReader.Read() == false)
                {
                    return;
                }
            }

            if (jsonReader.TokenType != JsonToken.StartObject)
            {
                throw new InvalidDataException("StartObject was expected");
            }

            // should read indexes now
            if (jsonReader.Read() == false)
            {
                return;
            }
            if (jsonReader.TokenType != JsonToken.PropertyName)
            {
                throw new InvalidDataException("PropertyName was expected");
            }
            if (Equals("Indexes", jsonReader.Value) == false)
            {
                throw new InvalidDataException("Indexes property was expected");
            }
            if (jsonReader.Read() == false)
            {
                return;
            }
            if (jsonReader.TokenType != JsonToken.StartArray)
            {
                throw new InvalidDataException("StartArray was expected");
            }

            while (jsonReader.Read() && jsonReader.TokenType != JsonToken.EndArray)
            {
                var index = RavenJToken.ReadFrom(jsonReader);
                if (options.OperateOnTypes.HasFlag(ItemType.Indexes) == false)
                {
                    continue;
                }
                var indexName = index.Value <string>("name");
                if (indexName.StartsWith("Raven/") || indexName.StartsWith("Temp/"))
                {
                    continue;
                }

                var request = CreateRequest("/indexes/" + indexName, "PUT");
                request.Write(index.Value <RavenJObject>("definition"));
                request.ExecuteRequest();
            }

            // should read documents now
            if (jsonReader.Read() == false)
            {
                return;
            }
            if (jsonReader.TokenType != JsonToken.PropertyName)
            {
                throw new InvalidDataException("PropertyName was expected");
            }
            if (Equals("Docs", jsonReader.Value) == false)
            {
                throw new InvalidDataException("Docs property was expected");
            }
            if (jsonReader.Read() == false)
            {
                return;
            }
            if (jsonReader.TokenType != JsonToken.StartArray)
            {
                throw new InvalidDataException("StartArray was expected");
            }
            var batch      = new List <RavenJObject>();
            int totalCount = 0;

            while (jsonReader.Read() && jsonReader.TokenType != JsonToken.EndArray)
            {
                var document = (RavenJObject)RavenJToken.ReadFrom(jsonReader);
                if (options.OperateOnTypes.HasFlag(ItemType.Documents) == false)
                {
                    continue;
                }
                if (options.MatchFilters(document) == false)
                {
                    continue;
                }

                totalCount += 1;
                batch.Add(document);
                if (batch.Count >= 128)
                {
                    FlushBatch(batch);
                }
            }
            FlushBatch(batch);

            var attachmentCount = 0;

            if (jsonReader.Read() == false || jsonReader.TokenType == JsonToken.EndObject)
            {
                return;
            }
            if (jsonReader.TokenType != JsonToken.PropertyName)
            {
                throw new InvalidDataException("PropertyName was expected");
            }
            if (Equals("Attachments", jsonReader.Value) == false)
            {
                throw new InvalidDataException("Attachment property was expected");
            }
            if (jsonReader.Read() == false)
            {
                return;
            }
            if (jsonReader.TokenType != JsonToken.StartArray)
            {
                throw new InvalidDataException("StartArray was expected");
            }
            while (jsonReader.Read() && jsonReader.TokenType != JsonToken.EndArray)
            {
                attachmentCount += 1;
                var item = RavenJToken.ReadFrom(jsonReader);
                if (options.OperateOnTypes.HasFlag(ItemType.Attachments) == false)
                {
                    continue;
                }
                var attachmentExportInfo =
                    new JsonSerializer
                {
                    Converters = { new TrivialJsonToJsonJsonConverter() }
                }.Deserialize <AttachmentExportInfo>(new RavenJTokenReader(item));
                Console.WriteLine("Importing attachment {0}", attachmentExportInfo.Key);

                var request = CreateRequest("/static/" + attachmentExportInfo.Key, "PUT");
                if (attachmentExportInfo.Metadata != null)
                {
                    foreach (var header in attachmentExportInfo.Metadata)
                    {
                        switch (header.Key)
                        {
                        case "Content-Type":
                            request.WebRequest.ContentType = header.Value.Value <string>();
                            break;

                        default:
                            request.WebRequest.Headers.Add(header.Key, StripQuotesIfNeeded(header.Value));
                            break;
                        }
                    }
                }

                request.Write(attachmentExportInfo.Data);
                request.ExecuteRequest();
            }
            Console.WriteLine("Imported {0:#,#;;0} documents and {1:#,#;;0} attachments in {2:#,#;;0} ms", totalCount, attachmentCount, sw.ElapsedMilliseconds);
        }