Пример #1
0
        public async Task NoLeakForContestedRequests_ThatAreEventuallyAdmitted(int contestingNumbers)
        {
            var sem       = new AsyncSemaphore(1);
            var releasers = new Task <AsyncSemaphore.Releaser> [contestingNumbers];

            await this.CheckGCPressureAsync(
                async delegate
            {
                var blockingReleaser = await sem.EnterAsync();
                for (int i = 0; i < releasers.Length; i++)
                {
                    releasers[i] = sem.EnterAsync();
                }

                // Now let the first one in.
                blockingReleaser.Dispose();

                // Now dispose the first one, and each one afterward as it is let in.
                for (int i = 0; i < releasers.Length; i++)
                {
                    (await releasers[i]).Dispose();
                }
            },
                maxBytesAllocated : -1,
                iterations : 5);
        }
Пример #2
0
        public async Task CurrentCount()
        {
            const int initialCapacity = 3;
            var       sem             = new AsyncSemaphore(initialCapacity);

            Assert.Equal(initialCapacity, sem.CurrentCount);

            var releasers = new AsyncSemaphore.Releaser[initialCapacity];

            for (int i = 0; i < initialCapacity; i++)
            {
                releasers[i] = await sem.EnterAsync();

                Assert.Equal(initialCapacity - (i + 1), sem.CurrentCount);
            }

            // After requesting another beyond its capacity, it should still report 0.
            var extraReleaser = sem.EnterAsync();

            Assert.Equal(0, sem.CurrentCount);

            for (int i = 0; i < initialCapacity; i++)
            {
                releasers[i].Dispose();
                Assert.Equal(i, sem.CurrentCount);
            }

            extraReleaser.Result.Dispose();
            Assert.Equal(initialCapacity, sem.CurrentCount);
        }
Пример #3
0
        public async Task StartLoading(string title = null, bool isCancelable = false)
        {
            using (await _lock.EnterAsync())
            {
                var currentCount = Interlocked.Increment(ref _loadingItems);
                if (currentCount == 1)
                {
                    await RunOnUIAsync(async() =>
                    {
                        _progressController = await ShellView.ShowChocolateyDialogAsync(title, isCancelable);
                        _progressController.SetIndeterminate();
                        if (isCancelable)
                        {
                            _cst = new CancellationTokenSource();
                            _progressController.OnCanceled += dialog =>
                            {
                                if (_cst != null)
                                {
                                    _cst.Cancel();
                                }
                            };
                        }

                        Output.Clear();

                        IsLoading = true;
                        NotifyPropertyChanged("IsLoading");
                    });
                }
            }
        }
Пример #4
0
        // 获得一个连接
        public static async Task <OpenConnectionResult> OpenConnectionAsync(string userNameAndUrl)
        {
            using (var releaser = await _limit.EnterAsync())
            {
                P2PConnection connection = _table[userNameAndUrl] as P2PConnection;
                if (connection != null)
                {
                    // 尝试连接一次
                    if (connection.IsDisconnected == true)
                    {
                        await EnsureConnectMessageServerAsync(
                            connection,
                            userNameAndUrl);
                    }
                    return(new OpenConnectionResult
                    {
                        Value = 0,
                        Connection = connection
                    });
                }

                var accounts = MessageAccountForm.GetAccounts();
                var account  = FindAccount(accounts, userNameAndUrl);
                if (account == null)
                {
                    return(new OpenConnectionResult
                    {
                        Value = -1,
                        ErrorInfo = $"用户名 '{userNameAndUrl}' 没有找到"
                    });
                }

                connection             = new P2PConnection();
                _table[userNameAndUrl] = connection;

                var result = await connection.ConnectAsync(account.ServerUrl,
                                                           account.UserName,
                                                           account.Password,
                                                           "");

                if (result.Value == -1)
                {
                    return new OpenConnectionResult
                           {
                               Value     = -1,
                               ErrorInfo = result.ErrorInfo,
                               ErrorCode = result.ErrorCode
                           }
                }
                ;
                return(new OpenConnectionResult
                {
                    Value = 0,
                    Connection = connection
                });
            }
        }
Пример #5
0
 public static async Task LoadKeeperAsync()
 {
     await Task.Run(async() =>
     {
         using (await semaphoreSlim.EnterAsync())
         {
             PasswordKeeper = await DataLoader.LoadFromFileAsync(await GetPwdFileAsync(), Password);
         }
     });
 }
Пример #6
0
 public async Task EnsureCreatedAsync()
 {
     using (var releaser = await _databaseLimit.EnterAsync())
     {
         using (var context = new QueueContext(_databaseFileName))
         {
             context.Database.EnsureCreated();
         }
     }
 }
Пример #7
0
        public void TwoResourceSemaphore()
        {
            var sem    = new AsyncSemaphore(2);
            var first  = sem.EnterAsync();
            var second = sem.EnterAsync();
            var third  = sem.EnterAsync();

            Assert.Equal(TaskStatus.RanToCompletion, first.Status);
            Assert.Equal(TaskStatus.RanToCompletion, second.Status);
            Assert.False(third.IsCompleted);
        }
Пример #8
0
        public async Task DiscoverRepositoryAsync(string filePath, CancellationToken cancellationToken)
        {
            Requires.NotNullOrEmpty(filePath, nameof(filePath));

            // Switch to background thread on purpose to avoid blocking the main thread.
            await TaskScheduler.Default;

            using (await _semaphore.EnterAsync(cancellationToken))
            {
                await DiscoverRepositoryInternalAsync(filePath, cancellationToken);
            }
        }
Пример #9
0
        public async Task <MessageDialogResult> ShowMessageAsync(string title, string message)
        {
            using (await _lock.EnterAsync())
            {
                if (ShellView != null)
                {
                    return(await RunOnUIAsync(() => ShellView.ShowMessageAsync(title, message)));
                }

                return(MessageBox.Show(message, title) == MessageBoxResult.OK
                           ? MessageDialogResult.Affirmative
                           : MessageDialogResult.Negative);
            }
        }
Пример #10
0
        // sync/commerror/normalerror/空
        // 同步成功/通讯出错/一般出错/从未同步过

        // 从外部存储中装载尚未同步的 Actions
        // 注意:这些 Actions 应该先按照 PII 排序分组以后,一组一组进行处理
        public static async Task <List <ActionInfo> > LoadRetryActionsFromDatabaseAsync()
        {
            using (var releaser = await _databaseLimit.EnterAsync())
            {
                using (var context = new RequestContext())
                {
                    context.Database.EnsureCreated();
                    var items = context.Requests.Where(o => o.State != "sync" && o.State != "dontsync")
                                .OrderBy(o => o.ID).ToList();
                    var actions = FromRequests(items);
                    WpfClientInfo.WriteInfoLog($"从本地数据库装载 Actions 成功。内容如下:\r\n{ActionInfo.ToString(actions)}");
                    return(actions);
                }
            }
        }
 protected async Task ExecuteWithLockAsync(Func <Task> func)
 {
     using (await _projectChangedSemaphore.EnterAsync().ConfigureAwait(false))
     {
         await func().ConfigureAwait(false);
     }
 }
        public async Task <T> WithLimitedCalls <T>(Func <Task <T> > onClient)
        {
            using (await _asyncSemaphore.EnterAsync(CancellationToken.None).ConfigureAwait(true))
            {
                var timeSpan = GetDelay();

                if ((DateTime.UtcNow - _lastCall).TotalSeconds < 2)
                {
                    Console.WriteLine($"Limited Caller ID: {Guid} With Delay: {timeSpan.TotalSeconds}");
                    await Task.Delay(timeSpan).ConfigureAwait(true);
                }
                else
                {
                    Console.WriteLine($"Limited Caller ID: {Guid} Without delay");
                }


                var res = await onClient().ConfigureAwait(true);

                lock (_lock)
                {
                    _lastCall = DateTime.UtcNow;
                }

                return(res);
            }
        }
Пример #13
0
        public async Task <IConnection> GetConnectionAsync()
        {
            var connection = _sharedConnection;

            if (connection == null || !connection.Open)
            {
                using (await _mutex.EnterAsync())
                {
                    connection = _sharedConnection;
                    if (connection == null || connection.Open)
                    {
                        _sharedConnection = null;
                        try
                        {
                            connection?.Dispose();
                        }
                        catch (Exception ex)
                        {
                            _logger.LogError(ex, "Disposing rethinkdb connection failed");
                        }
                        _sharedConnection = connection = await CreateConnectionAsync();
                    }
                }
            }
            return(connection);
        }
        public async Task <ProjectSnapshotManagerProxyState> GetProjectManagerStateAsync(CancellationToken cancellationToken)
        {
            using (await _latestStateSemaphore.EnterAsync().ConfigureAwait(false))
            {
                if (_latestState != null)
                {
                    return(_latestState);
                }
            }

            var projects = await GetLatestProjectsAsync();

            var state = await CalculateUpdatedStateAsync(projects);

            return(state);
        }
Пример #15
0
        public void InitialCapacityZero()
        {
            var sem = new AsyncSemaphore(0);

            Assert.Equal(0, sem.CurrentCount);
            Assert.False(sem.EnterAsync().IsCompleted);
            Assert.Equal(0, sem.CurrentCount);
        }
Пример #16
0
        /// <inheritdoc />
        public async Task <MessageDialogResult> ShowMessageAsync(string title, string message)
        {
            using (await _lock.EnterAsync())
            {
                if (ShellView != null)
                {
                    var dialogSettings = new MetroDialogSettings
                    {
                        AffirmativeButtonText = Resources.ChocolateyDialog_OK
                    };

                    return(await ShellView.Dispatcher.Invoke(async() => { return await ShellView.ShowMessageAsync(title, message, MessageDialogStyle.Affirmative, dialogSettings); }));
                }

                return(MessageBox.Show(message, title) == MessageBoxResult.OK
                    ? MessageDialogResult.Affirmative
                    : MessageDialogResult.Negative);
            }
        }
Пример #17
0
 private async Task <models.File> UploadThreaded(RemoteFile file, Uri parent)
 {
     using (await threadedUploadQueue.EnterAsync())
         using (var platformFile = new LazyPlatformFileStream(file))
         {
             var uploader = api.GetAsyncFileUploader(
                 BuildUploadSpecificationRequest(file, parent, models.UploadMethod.Threaded),
                 platformFile, threadedUploaderConfig);
             return(UploadResultToModel((await uploader.UploadAsync()).First()));
         }
 }
Пример #18
0
 protected async Task ExecuteWithLock(Func <Task> func)
 {
     using (JoinableCollection.Join())
     {
         using (await _lock.EnterAsync().ConfigureAwait(false))
         {
             var task = JoinableFactory.RunAsync(func);
             await task.Task.ConfigureAwait(false);
         }
     }
 }
Пример #19
0
        public async Task TooManyReleases_CopyOfStruct()
        {
            var sem       = new AsyncSemaphore(2);
            var releaser1 = await sem.EnterAsync();

            var releaser2 = await sem.EnterAsync();

            // Assigning the releaser struct to another local variable copies it.
            var releaser2Copy = releaser2;

            // Dispose of each copy of the releaser.
            // The double-release is undetectable. The semaphore should be back at capacity 2.
            releaser2.Dispose();
            Assert.Equal(1, sem.CurrentCount);
            releaser2Copy.Dispose();
            Assert.Equal(2, sem.CurrentCount);

            releaser1.Dispose();
            Assert.Equal(3, sem.CurrentCount);
        }
Пример #20
0
        private async Task ProjectChangedBackgroundAsync(object state)
        {
            _batchingProjectChanges = false;

            // Ensure ordering, typically we'll only have 1 background thread in flight at a time. However,
            // between this line and the one prior another background thread could have also entered this
            // method. This is here to protect against us changing the order of project changed events.
            using (await _onProjectChangedInnerSemaphore.EnterAsync().ConfigureAwait(false))
            {
                await OnProjectChangedAsync();
            }
        }
        private async Task ExecuteInitScriptsAsync()
        {
            // Fix for Bug 1426 Disallow ExecuteInitScripts from being executed concurrently by multiple threads.
            using (await _initScriptsLock.EnterAsync())
            {
                if (!await _solutionManager.Value.IsSolutionOpenAsync())
                {
                    return;
                }

                Debug.Assert(_settings != null);
                if (_settings == null)
                {
                    return;
                }

                var latestRestore           = _latestRestore;
                var latestSolutionDirectory = await _solutionManager.Value.GetSolutionDirectoryAsync();

                if (ShouldNoOpDueToRestore(latestRestore) &&
                    ShouldNoOpDueToSolutionDirectory(latestSolutionDirectory))
                {
                    _currentRestore           = latestRestore;
                    _currentSolutionDirectory = latestSolutionDirectory;

                    return;
                }
                // We may be enumerating packages from disk here. Always do it from a background thread.
                await TaskScheduler.Default;

                var packageManager = new NuGetPackageManager(
                    _sourceRepositoryProvider,
                    _settings.Value,
                    _solutionManager.Value,
                    _deleteOnRestartManager.Value,
                    _restoreProgressReporter.Value);

                var enumerator        = new InstalledPackageEnumerator(_solutionManager.Value, _settings.Value);
                var installedPackages = await enumerator.EnumeratePackagesAsync(packageManager, CancellationToken.None);

                foreach (var installedPackage in installedPackages)
                {
                    await ExecuteInitPs1Async(installedPackage.InstallPath, installedPackage.Identity);
                }

                // We are done executing scripts, so record the restore and solution directory that we executed for.
                // This aids the no-op logic above.
                _currentRestore           = latestRestore;
                _currentSolutionDirectory = latestSolutionDirectory;
            }
        }
Пример #22
0
        private async Task WriteToOutputChannelAsync(string channelId, string displayNameResourceId, string content, CancellationToken cancellationToken)
        {
            using (await _pipeLock.EnterAsync())
            {
                if (_channelPipeWriter == null)
                {
                    var pipe = new Pipe();

                    using (var outputChannelStore = await(await _serviceBrokerClient.GetValueAsync()).GetProxyAsync <IOutputChannelStore>(VisualStudioServices.VS2019_4.OutputChannelStore, cancellationToken))
                    {
                        if (outputChannelStore.Proxy != null)
                        {
                            await outputChannelStore.Proxy.CreateChannelAsync(channelId, displayNameResourceId, pipe.Reader, TextEncoding, cancellationToken);

                            _channelPipeWriter = pipe.Writer;

                            // write any deferred messages
                            foreach (var defferedMessage in _deferredOutputMessages)
                            {
                                // Flush when the original content is logged below
                                await _channelPipeWriter.WriteAsync(GetBytes(defferedMessage), cancellationToken);
                            }
                            _deferredOutputMessages.Clear();
                        }
                        else
                        {
                            // OutputChannel is not available so cache the output messages for later
                            _deferredOutputMessages.Add(content);
                            return;
                        }
                    }
                }
                await _channelPipeWriter.WriteAsync(GetBytes(content), cancellationToken);

                await _channelPipeWriter.FlushAsync(cancellationToken);
            }
        }
Пример #23
0
        public async Task NoLeakForAllCanceledRequests()
        {
            var sem = new AsyncSemaphore(0);

            await this.CheckGCPressureAsync(
                async delegate
            {
                var cts       = new CancellationTokenSource();
                var enterTask = sem.EnterAsync(cts.Token);
                cts.Cancel();
                await enterTask.NoThrowAwaitable();
            },
                maxBytesAllocated : -1,
                iterations : 5);
        }
Пример #24
0
        public async Task SearchForNewObjectsAsync()
        {
            // Do not allow more than one thread to do this concurrently
            using (await _querySemaphore.EnterAsync())
            {
                _lastQueryCheck = DateTime.UtcNow;

                // Find maximum NeDesigns ID
                var obj = await _rctObjectRepo.GetLegacyObjectWithHighestNeIdAsync();

                if (obj != null)
                {
                    var neId  = obj.NeDesignId;
                    var fails = 0;
                    while (fails < 3)
                    {
                        neId++;
                        try
                        {
                            _logger.LogInformation($"Querying NEDesigns for object id: {neId}");
                            var queryUrl  = $"https://www.nedesigns.com/rct2-object/{neId}/x/";
                            var queryHtml = await _httpClient.GetStringAsync(queryUrl);

                            var match = Regex.Match(queryHtml, $"/rct2-object/{neId}/(.+)/download/");
                            if (match.Success)
                            {
                                var name = match.Groups[1].Value.ToUpperInvariant();
                                await _rctObjectRepo.UpdateLegacyAsync(
                                    new LegacyRctObject()
                                {
                                    NeDesignId = neId, Name = name
                                });

                                _logger.LogInformation($"Adding new object: #{neId} [{name}]");
                            }
                        }
                        catch (Exception ex)
                        {
                            _logger.LogWarning(ex, $"Failed to query object {neId}");
                            fails++;
                        }
                    }
                }
            }
        }
Пример #25
0
        public async Task NoLeakForContestedRequests_ThatAreCanceled(int contestingNumbers)
        {
            var sem       = new AsyncSemaphore(0);
            var releasers = new Task <AsyncSemaphore.Releaser> [contestingNumbers];

            await this.CheckGCPressureAsync(
                async delegate
            {
                var cts = new CancellationTokenSource();
                for (int i = 0; i < releasers.Length; i++)
                {
                    releasers[i] = sem.EnterAsync(cts.Token);
                }

                cts.Cancel();
                await Task.WhenAll(releasers).NoThrowAwaitable();
            },
                maxBytesAllocated : -1,
                iterations : 5);
        }
Пример #26
0
        public async Task NoLeakForUncontestedRequests(int initialCapacity)
        {
            var sem       = new AsyncSemaphore(initialCapacity);
            var releasers = new AsyncSemaphore.Releaser[initialCapacity];

            await this.CheckGCPressureAsync(
                async delegate
            {
                for (int i = 0; i < releasers.Length; i++)
                {
                    releasers[i] = await sem.EnterAsync();
                }

                for (int i = 0; i < releasers.Length; i++)
                {
                    releasers[i].Dispose();
                }
            },
                maxBytesAllocated : -1,
                iterations : 5);
        }
Пример #27
0
        public async Task AddSecretAsync(string name, string value, CancellationToken cancellationToken = default)
        {
            EnsureKeyNameIsValid(name);
            await TaskScheduler.Default;

            using (await _semaphore.EnterAsync(cancellationToken))
                using (var store = await GetOrCreateStoreAsync(cancellationToken))
                {
                    if (store.ContainsKey(name))
                    {
                        throw new ArgumentException(Resources.Error_SecretAlreadyExists, nameof(name));
                    }

                    store.Set(name, value);
                    await store.SaveAsync(cancellationToken);
                }
        }
Пример #28
0
        private async Task ExecuteInitScriptsAsync()
        {
            // Fix for Bug 1426 Disallow ExecuteInitScripts from being executed concurrently by multiple threads.
            using (await _initScriptsLock.EnterAsync())
            {
                if (!_solutionManager.IsSolutionOpen)
                {
                    return;
                }

                Debug.Assert(_settings != null);
                if (_settings == null)
                {
                    return;
                }

                var latestRestore           = _latestRestore;
                var latestSolutionDirectory = _solutionManager.SolutionDirectory;
                if (ShouldNoOpDueToRestore(latestRestore) &&
                    ShouldNoOpDueToSolutionDirectory(latestSolutionDirectory))
                {
                    _currentRestore           = latestRestore;
                    _currentSolutionDirectory = latestSolutionDirectory;

                    return;
                }

                // invoke init.ps1 files in the order of package dependency.
                // if A -> B, we invoke B's init.ps1 before A's.

                var projects       = _solutionManager.GetNuGetProjects().ToList();
                var packageManager = new NuGetPackageManager(
                    _sourceRepositoryProvider,
                    _settings,
                    _solutionManager,
                    _deleteOnRestartManager);

                var packagesByFramework  = new Dictionary <NuGetFramework, HashSet <PackageIdentity> >();
                var sortedGlobalPackages = new List <PackageIdentity>();

                // Sort projects by type
                foreach (var project in projects)
                {
                    // Skip project K projects.
                    if (project is ProjectKNuGetProjectBase)
                    {
                        continue;
                    }

                    var buildIntegratedProject = project as BuildIntegratedNuGetProject;

                    if (buildIntegratedProject != null)
                    {
                        var packages = await BuildIntegratedProjectUtility
                                       .GetOrderedProjectPackageDependencies(buildIntegratedProject);

                        sortedGlobalPackages.AddRange(packages);
                    }
                    else
                    {
                        // Read packages.config
                        var installedRefs = await project.GetInstalledPackagesAsync(CancellationToken.None);

                        if (installedRefs?.Any() == true)
                        {
                            // Index packages.config references by target framework since this affects dependencies
                            NuGetFramework targetFramework;
                            if (!project.TryGetMetadata(NuGetProjectMetadataKeys.TargetFramework, out targetFramework))
                            {
                                targetFramework = NuGetFramework.AnyFramework;
                            }

                            HashSet <PackageIdentity> fwPackages;
                            if (!packagesByFramework.TryGetValue(targetFramework, out fwPackages))
                            {
                                fwPackages = new HashSet <PackageIdentity>();
                                packagesByFramework.Add(targetFramework, fwPackages);
                            }

                            fwPackages.UnionWith(installedRefs.Select(reference => reference.PackageIdentity));
                        }
                    }
                }

                // Each id/version should only be executed once
                var finishedPackages = new HashSet <PackageIdentity>();

                // Packages.config projects
                if (packagesByFramework.Count > 0)
                {
                    await ExecuteInitPs1ForPackagesConfig(
                        packageManager,
                        packagesByFramework,
                        finishedPackages);
                }

                // build integrated projects
                if (sortedGlobalPackages.Count > 0)
                {
                    await ExecuteInitPs1ForBuildIntegratedAsync(
                        sortedGlobalPackages,
                        finishedPackages);
                }

                // We are done executing scripts, so record the restore and solution directory that we executed for.
                // This aids the no-op logic above.
                _currentRestore           = latestRestore;
                _currentSolutionDirectory = latestSolutionDirectory;
            }
        }
Пример #29
0
        // 获得册记录信息和书目摘要信息
        // parameters:
        //      style   风格。network 表示只从网络获取册记录;否则优先从本地获取,本地没有再从网络获取册记录。无论如何,书目摘要都是尽量从本地获取
        // .Value
        //      0   没有找到
        //      1   找到
        public static async Task <GetEntityDataResult> GetEntityDataAsync(string pii,
                                                                          string style)
        {
            bool network = StringUtil.IsInList("network", style);

            try
            {
                using (var releaser = await _channelLimit.EnterAsync())
                    using (BiblioCacheContext context = new BiblioCacheContext())
                    {
                        if (_cacheDbCreated == false)
                        {
                            context.Database.EnsureCreated();
                            _cacheDbCreated = true;
                        }

                        LibraryChannel channel     = App.CurrentApp.GetChannel();
                        TimeSpan       old_timeout = channel.Timeout;
                        channel.Timeout = TimeSpan.FromSeconds(10);
                        try
                        {
                            GetEntityDataResult result = null;
                            List <NormalResult> errors = new List <NormalResult>();

                            EntityItem entity_record = null;

                            // ***
                            // 第一步:获取册记录

                            if (network == false)
                            {
                                // 先尝试从本地实体库中获得记录
                                entity_record = context.Entities.Where(o => o.PII == pii).FirstOrDefault();
                                // EntityItem entity_record = null;   // testing
                            }

                            if (entity_record != null)
                            {
                                result = new GetEntityDataResult
                                {
                                    Value       = 1,
                                    ItemXml     = entity_record.Xml,
                                    ItemRecPath = entity_record.RecPath,
                                    Title       = "",
                                }
                            }
                            ;
                            else
                            {
                                // 再尝试从 dp2library 服务器获取
                                // TODO: ItemXml 和 BiblioSummary 可以考虑在本地缓存一段时间
                                int nRedoCount = 0;
REDO_GETITEMINFO:
                                long lRet = channel.GetItemInfo(null,
                                                                "item",
                                                                pii,
                                                                "",
                                                                "xml",
                                                                out string item_xml,
                                                                out string item_recpath,
                                                                out byte[] timestamp,
                                                                "",
                                                                out _,
                                                                out _,
                                                                out string strError);
                                if (lRet == -1)
                                {
                                    if ((channel.ErrorCode == ErrorCode.RequestError ||
                                         channel.ErrorCode == ErrorCode.RequestTimeOut) &&
                                        nRedoCount < 2)
                                    {
                                        nRedoCount++;
                                        goto REDO_GETITEMINFO;
                                    }
                                    // TODO: 这里不着急返回,还需要尝试获得书目摘要
                                    errors.Add(new NormalResult
                                    {
                                        Value     = -1,
                                        ErrorInfo = strError,
                                        ErrorCode = channel.ErrorCode.ToString()
                                    });

                                    /*
                                     * return new GetEntityDataResult
                                     * {
                                     *  Value = -1,
                                     *  ErrorInfo = strError,
                                     *  ErrorCode = channel.ErrorCode.ToString()
                                     * };
                                     */
                                }
                                else
                                {
                                    result = new GetEntityDataResult
                                    {
                                        Value       = 1,
                                        ItemXml     = item_xml,
                                        ItemRecPath = item_recpath,
                                        Title       = "",
                                    };

                                    // 保存到本地数据库
                                    await AddOrUpdateAsync(context, new EntityItem
                                    {
                                        PII       = pii,
                                        Xml       = item_xml,
                                        RecPath   = item_recpath,
                                        Timestamp = timestamp,
                                    });

#if NO
                                    context.Entities.Add(new EntityItem
                                    {
                                        PII       = pii,
                                        Xml       = item_xml,
                                        RecPath   = item_recpath,
                                        Timestamp = timestamp,
                                    });
                                    try
                                    {
                                        await context.SaveChangesAsync();
                                    }
                                    catch (Exception ex)
                                    {
                                        SqliteException sqlite_exception = ex.InnerException as SqliteException;
                                        if (sqlite_exception != null && sqlite_exception.SqliteErrorCode == 19)
                                        {
                                            // PII 发生重复了
                                        }
                                        else
                                        {
                                            throw ex;
                                        }
                                    }
#endif
                                }
                            }

                            // ***
                            /// 第二步:获取书目摘要

                            // 先尝试从本地书目库中获取书目摘要

                            var item = context.BiblioSummaries.Where(o => o.PII == pii).FirstOrDefault();
                            if (item != null &&
                                string.IsNullOrEmpty(item.BiblioSummary) == false)
                            {
                                if (result == null)
                                {
                                    result = new GetEntityDataResult();
                                }

                                result.Title = item.BiblioSummary;
                            }
                            else
                            {
                                // 从 dp2library 服务器获取书目摘要
                                int nRedoCount = 0;
REDO_GETBIBLIOSUMMARY:
                                long lRet = channel.GetBiblioSummary(
                                    null,
                                    pii,
                                    "", // strConfirmItemRecPath,
                                    null,
                                    out _,
                                    out string strSummary,
                                    out string strError);
                                if (lRet == -1)
                                {
                                    if ((channel.ErrorCode == ErrorCode.RequestError ||
                                         channel.ErrorCode == ErrorCode.RequestTimeOut) &&
                                        nRedoCount < 2)
                                    {
                                        nRedoCount++;
                                        goto REDO_GETBIBLIOSUMMARY;
                                    }

                                    errors.Add(new NormalResult
                                    {
                                        Value     = -1,
                                        ErrorInfo = strError,
                                        ErrorCode = channel.ErrorCode.ToString()
                                    });

                                    /*
                                     * return new GetEntityDataResult
                                     * {
                                     *  Value = -1,
                                     *  ErrorInfo = strError,
                                     *  ErrorCode = channel.ErrorCode.ToString(),
                                     * };
                                     */
                                }
                                else
                                {
                                    strSummary = strSummary?.Replace(". -- ", "\r\n"); // .Replace("/", "\r\n");

                                    if (result == null)
                                    {
                                        result = new GetEntityDataResult();
                                    }

                                    result.Title = strSummary;

                                    // 存入数据库备用
                                    if (lRet == 1 && string.IsNullOrEmpty(strSummary) == false)
                                    {
                                        try
                                        {
                                            var exist_item = context.BiblioSummaries.Where(o => o.PII == pii).FirstOrDefault();

                                            if (exist_item != null)
                                            {
                                                if (exist_item.BiblioSummary != strSummary)
                                                {
                                                    exist_item.BiblioSummary = strSummary;
                                                    context.BiblioSummaries.Update(exist_item);
                                                }
                                            }
                                            else
                                            {
                                                context.BiblioSummaries.Add(new BiblioSummaryItem
                                                {
                                                    PII           = pii,
                                                    BiblioSummary = strSummary
                                                });
                                            }
                                            await context.SaveChangesAsync();
                                        }
                                        catch (Exception ex)
                                        {
                                            WpfClientInfo.WriteErrorLog($"GetEntityDataAsync() 中保存 summary 时(PII 为 '{pii}')出现异常:{ExceptionUtil.GetDebugText(ex)}");
                                        }
                                    }
                                }

                                /*
                                 * return new GetEntityDataResult
                                 * {
                                 *  Value = (int)lRet,
                                 *  ItemXml = item_xml,
                                 *  ItemRecPath = item_recpath,
                                 *  Title = strSummary,
                                 *  ErrorInfo = strError,
                                 *  ErrorCode = channel.ErrorCode.ToString()
                                 * };
                                 */
                            }

                            // 完全成功
                            if (result != null && errors.Count == 0)
                            {
                                return(result);
                            }
                            if (result == null)
                            {
                                return new GetEntityDataResult
                                       {
                                           Value     = errors[0].Value,
                                           ErrorInfo = errors[0].ErrorInfo,
                                           ErrorCode = errors[0].ErrorCode
                                       }
                            }
                            ;
                            result.ErrorInfo = errors[0].ErrorInfo;
                            result.ErrorCode = errors[0].ErrorCode;
                            return(result);
                        }
                        finally
                        {
                            channel.Timeout = old_timeout;
                            App.CurrentApp.ReturnChannel(channel);
                        }
                    }
            }
            catch (Exception ex)
            {
                WpfClientInfo.WriteErrorLog($"GetEntityDataAsync() 出现异常: {ExceptionUtil.GetDebugText(ex)}");

                return(new GetEntityDataResult
                {
                    Value = -1,
                    ErrorInfo = $"GetEntityDataAsync() 出现异常: {ex.Message}",
                    ErrorCode = ex.GetType().ToString()
                });
            }
        }
Пример #30
0
        // 获得册记录信息和书目摘要信息
        // parameters:
        //      style   风格。network 表示只从网络获取册记录;否则优先从本地获取,本地没有再从网络获取册记录。无论如何,书目摘要都是尽量从本地获取
        // .Value
        //      0   没有找到
        //      1   找到
        public static async Task <GetEntityDataResult> GetEntityDataAsync(string pii,
                                                                          string style)
        {
            bool network = StringUtil.IsInList("network", style);

            try
            {
                using (var releaser = await _channelLimit.EnterAsync())
                {
                    SipChannel channel = await GetChannelAsync();

                    try
                    {
                        GetEntityDataResult result = null;
                        List <NormalResult> errors = new List <NormalResult>();

                        EntityItem entity_record = null;

                        // ***
                        // 第一步:获取册记录

                        {
                            // 再尝试从 dp2library 服务器获取
                            // TODO: ItemXml 和 BiblioSummary 可以考虑在本地缓存一段时间
                            int nRedoCount = 0;
REDO_GETITEMINFO:
                            var get_result = await _channel.GetItemInfoAsync("", pii);

                            if (get_result.Value == -1)
                            {
                                errors.Add(new NormalResult
                                {
                                    Value     = -1,
                                    ErrorInfo = get_result.ErrorInfo,
                                    ErrorCode = get_result.ErrorCode
                                });
                            }
                            else if (get_result.Result.CirculationStatus_2 == "01")
                            {
                                errors.Add(new NormalResult
                                {
                                    Value     = -1,
                                    ErrorInfo = get_result.Result.AF_ScreenMessage_o,
                                    ErrorCode = get_result.Result.CirculationStatus_2
                                });
                            }
                            else if (get_result.Result.CirculationStatus_2 == "13")
                            {
                                errors.Add(new NormalResult
                                {
                                    Value     = -1,
                                    ErrorInfo = get_result.Result.AF_ScreenMessage_o,
                                    ErrorCode = "itemNotFound"
                                });
                            }
                            else
                            {
                                XmlDocument itemdom = new XmlDocument();
                                itemdom.LoadXml("<root />");

                                string state = "";
                                if (get_result.Result.CirculationStatus_2 == "12")
                                {
                                    state = "丢失";
                                }

                                DomUtil.SetElementText(itemdom.DocumentElement, "state", state);

                                DomUtil.SetElementText(itemdom.DocumentElement,
                                                       "barcode",
                                                       get_result.Result.AB_ItemIdentifier_r);
                                DomUtil.SetElementText(itemdom.DocumentElement,
                                                       "location",
                                                       get_result.Result.AQ_PermanentLocation_o);
                                DomUtil.SetElementText(itemdom.DocumentElement,
                                                       "currentLocation",
                                                       get_result.Result.AP_CurrentLocation_o);

                                DomUtil.SetElementText(itemdom.DocumentElement,
                                                       "accessNo",
                                                       get_result.Result.CH_ItemProperties_o);

                                // 借书时间
                                {
                                    string borrowDateString = get_result.Result.CM_HoldPickupDate_18;
                                    if (string.IsNullOrEmpty(borrowDateString) == false)
                                    {
                                        if (DateTime.TryParseExact(borrowDateString,
                                                                   "yyyyMMdd    HHmmss",
                                                                   CultureInfo.InvariantCulture,
                                                                   DateTimeStyles.None,
                                                                   out DateTime borrowDate))
                                        {
                                            DomUtil.SetElementText(itemdom.DocumentElement,
                                                                   "borrowDate",
                                                                   DateTimeUtil.Rfc1123DateTimeStringEx(borrowDate));

                                            DomUtil.SetElementText(itemdom.DocumentElement,
                                                                   "borrower",
                                                                   "***");
                                        }
                                        else
                                        {
                                            // 报错,时间字符串格式错误,无法解析
                                        }
                                    }
                                }

                                // 应还书时间
                                {
                                    string returnningDateString = get_result.Result.AH_DueDate_o;
                                    if (string.IsNullOrEmpty(returnningDateString) == false)
                                    {
                                        if (DateTime.TryParseExact(returnningDateString,
                                                                   DateFormat,
                                                                   CultureInfo.InvariantCulture,
                                                                   DateTimeStyles.None,
                                                                   out DateTime returningDate))
                                        {
                                            DomUtil.SetElementText(itemdom.DocumentElement,
                                                                   "returningDate",
                                                                   DateTimeUtil.Rfc1123DateTimeStringEx(returningDate));
                                        }
                                        else
                                        {
                                            // 报错,时间字符串格式错误,无法解析
                                        }
                                    }
                                }

                                result = new GetEntityDataResult
                                {
                                    Value       = 1,
                                    ItemXml     = itemdom.OuterXml,
                                    ItemRecPath = get_result.Result.AB_ItemIdentifier_r,
                                    Title       = get_result.Result.AJ_TitleIdentifier_r,
                                };

                                /*
                                 * // 保存到本地数据库
                                 * await AddOrUpdateAsync(context, new EntityItem
                                 * {
                                 *  PII = pii,
                                 *  Xml = item_xml,
                                 *  RecPath = item_recpath,
                                 *  Timestamp = timestamp,
                                 * });
                                 */
                            }
                        }

                        // ***
                        /// 第二步:获取书目摘要

                        // 完全成功
                        if (result != null && errors.Count == 0)
                        {
                            return(result);
                        }
                        if (result == null)
                        {
                            return new GetEntityDataResult
                                   {
                                       Value     = errors[0].Value,
                                       ErrorInfo = errors[0].ErrorInfo,
                                       ErrorCode = errors[0].ErrorCode
                                   }
                        }
                        ;
                        result.ErrorInfo = errors[0].ErrorInfo;
                        result.ErrorCode = errors[0].ErrorCode;
                        return(result);
                    }
                    finally
                    {
                        ReturnChannel(channel);
                    }
                }
            }
            catch (Exception ex)
            {
                WpfClientInfo.WriteErrorLog($"GetEntityDataAsync() 出现异常: {ExceptionUtil.GetDebugText(ex)}");

                return(new GetEntityDataResult
                {
                    Value = -1,
                    ErrorInfo = $"GetEntityDataAsync() 出现异常: {ex.Message}",
                    ErrorCode = ex.GetType().ToString()
                });
            }
        }