Ejemplo n.º 1
0
 public void Lock_Reentrancy_DoesNotBlock()
 {
     using (var mutex = new GlobalMutex("test"))
     {
         mutex.Initialize();
         using (mutex.Lock())
         {
             using (mutex.Lock()) {}
         }
     }
 }
Ejemplo n.º 2
0
        /// <summary>
        /// API to query the SLDR for an LDML file and save it locally in the SLDR cache and specified directories
        /// </summary>
        /// <param name="destinationPath">Destination path to save the requested LDML file</param>
        /// <param name="languageTag">Current IETF language tag</param>
        /// <param name="topLevelElements">List of top level element names to request. SLDR will always publish identity, so it doesn't need to be requested.
        /// If null, the entire LDML file will be requested.</param>
        /// <param name="filename">Saved filename</param>
        /// <returns>Enum status SldrStatus if file could be retrieved and the source</returns>
        public static SldrStatus GetLdmlFile(string destinationPath, string languageTag, IEnumerable <string> topLevelElements, out string filename)
        {
            CheckInitialized();

            if (String.IsNullOrEmpty(destinationPath))
            {
                throw new ArgumentException("destinationPath");
            }
            if (!Directory.Exists(destinationPath))
            {
                throw new DirectoryNotFoundException("destinationPath");
            }
            if (String.IsNullOrEmpty(languageTag) || (!IetfLanguageTag.IsValid(languageTag)))
            {
                throw new ArgumentException("ietfLanguageTag");
            }
            if (topLevelElements == null)
            {
                throw new ArgumentNullException("topLevelElements");
            }

            string sldrLanguageTag = IetfLanguageTag.Canonicalize(languageTag);
            SldrLanguageTagInfo langTagInfo;

            if (LanguageTags.TryGet(sldrLanguageTag, out langTagInfo))
            {
                sldrLanguageTag = langTagInfo.SldrLanguageTag;
            }
            string[] topLevelElementsArray = topLevelElements.ToArray();

            using (_sldrCacheMutex.Lock())
            {
                var status = SldrStatus.NotFound;
                CreateSldrCacheDirectory();
                string sldrCacheFilePath;
                bool   redirected;
                do
                {
                    string revid, uid = "", tempString;
                    if (destinationPath == SldrCachePath)
                    {
                        filename = string.Format("{0}.{1}", sldrLanguageTag, LdmlExtension);
                    }
                    else
                    {
                        filename = string.Format("{0}.{1}", languageTag, LdmlExtension);
                        // Check if LDML file already exists in destination and read revid and uid
                        if (!ReadSilIdentity(Path.Combine(destinationPath, filename), out tempString, out uid))
                        {
                            uid = DefaultUserId;
                        }
                    }

                    // If languageTag contains fonipa, don't bother trying to access the SLDR
                    if (sldrLanguageTag.Contains(WellKnownSubtags.IpaVariant) || sldrLanguageTag.Contains(WellKnownSubtags.AudioScript))
                    {
                        return(SldrStatus.NotFound);
                    }

                    sldrCacheFilePath = Path.Combine(SldrCachePath, !string.IsNullOrEmpty(uid) && uid != DefaultUserId ? string.Format("{0}-{1}.{2}", sldrLanguageTag, uid, LdmlExtension)
                                                : string.Format("{0}.{1}", sldrLanguageTag, LdmlExtension));
                    // Read revid from cache file
                    ReadSilIdentity(sldrCacheFilePath, out revid, out tempString);

                    // Concatenate parameters for url string
                    string requestedElements = string.Empty;
                    if (topLevelElementsArray.Length > 0)
                    {
                        requestedElements = string.Format("&inc[]={0}", string.Join("&inc[]=", topLevelElementsArray));
                    }
                    string requestedUserId = !string.IsNullOrEmpty(uid) ? string.Format("&uid={0}", uid) : string.Empty;
                    string requestedRevid  = !string.IsNullOrEmpty(revid) ? string.Format("&revid={0}", revid) : string.Empty;
                    string url             = string.Format("{0}{1}?ext={2}&flatten=1{3}{4}{5}",
                                                           SldrRepository, sldrLanguageTag, LdmlExtension,
                                                           requestedElements, requestedUserId, requestedRevid);

                    string tempFilePath = sldrCacheFilePath + "." + TmpExtension;

                    // Using WebRequest instead of WebClient so we have access to disable AllowAutoRedirect
                    var webRequest = (HttpWebRequest)WebRequest.Create(Uri.EscapeUriString(url));
                    webRequest.AllowAutoRedirect = false;
                    webRequest.UserAgent         = UserAgent;
                    webRequest.Timeout           = 10000;

                    try
                    {
                        if (_offlineMode)
                        {
                            throw new WebException("Test mode: SLDR offline so accessing cache", WebExceptionStatus.ConnectFailure);
                        }

                        // Check the response header to see if the requested LDML file got redirected
                        using (var webResponse = (HttpWebResponse)webRequest.GetResponse())
                        {
                            if (webResponse.StatusCode == HttpStatusCode.NotModified)
                            {
                                // Report status that file is the most current from SLDR
                                status     = SldrStatus.FromSldr;
                                redirected = false;
                            }
                            else if (webResponse.StatusCode == HttpStatusCode.MovedPermanently)
                            {
                                // Extract ietfLanguageTag from the response header
                                var parsedresponse = HttpUtilityFromMono.ParseQueryString(webResponse.Headers["Location"]);
                                sldrLanguageTag = parsedresponse.Get("ws_id").Split('?')[0];
                                redirected      = true;
                            }
                            else
                            {
                                // Download the LDML file to a temp file in case the transfer gets interrupted
                                using (Stream responseStream = webResponse.GetResponseStream())
                                    using (var fs = new FileStream(tempFilePath, FileMode.OpenOrCreate, FileAccess.Write))
                                    {
                                        var buff = new byte[102400];
                                        int c;
                                        while ((c = responseStream.Read(buff, 0, buff.Length)) > 0)
                                        {
                                            fs.Write(buff, 0, c);
                                            fs.Flush();
                                        }
                                    }

                                status            = SldrStatus.FromSldr;
                                sldrCacheFilePath = MoveTmpToCache(tempFilePath, uid);
                                redirected        = false;
                            }
                        }
                    }
                    catch (WebException we)
                    {
                        // Return from 404 error
                        var errorResponse = (HttpWebResponse)we.Response;
                        if ((we.Status == WebExceptionStatus.ProtocolError) && (errorResponse.StatusCode == HttpStatusCode.NotFound))
                        {
                            return(SldrStatus.NotFound);
                        }

                        string sldrCacheFilename;
                        // Download failed so check SLDR cache
                        if (!string.IsNullOrEmpty(uid) && (uid != DefaultUserId))
                        {
                            sldrCacheFilename = string.Format("{0}-{1}.{2}", sldrLanguageTag, uid, LdmlExtension);
                        }
                        else
                        {
                            sldrCacheFilename = string.Format("{0}.{1}", sldrLanguageTag, LdmlExtension);
                        }
                        sldrCacheFilePath = Path.Combine(SldrCachePath, sldrCacheFilename);
                        if (File.Exists(sldrCacheFilePath))
                        {
                            status = SldrStatus.FromCache;
                        }
                        else
                        {
                            return(SldrStatus.UnableToConnectToSldr);
                        }
                        redirected = false;
                    }
                    finally
                    {
                        if (File.Exists(tempFilePath))
                        {
                            File.Delete(tempFilePath);
                        }
                    }
                } while (redirected);

                if (destinationPath != SldrCachePath)
                {
                    // Copy from Cache to destination (w/o uid in filename), overwriting whatever used to be there
                    File.Copy(sldrCacheFilePath, Path.Combine(destinationPath, filename), true);
                }

                return(status);
            }
        }
        protected override void ShutdownInternal()
        {
            if (m_commitLogMutex != null && m_commitLogMetadata != null)
            {
                CompleteAllCommits();
                using (m_commitLogMutex.Lock())
                {
#if __MonoCS__
                    bool delete = false;
#endif
                    using (MemoryMappedViewStream stream = m_commitLogMetadata.CreateViewStream())
                    {
                        CommitLogMetadata metadata;
                        if (TryGetMetadata(stream, out metadata))
                        {
                            if (metadata.Master == m_peerID)
                            {
                                // commit any unseen foreign changes
                                List <ICmObjectSurrogate> foreignNewbies;
                                List <ICmObjectSurrogate> foreignDirtballs;
                                List <ICmObjectId>        foreignGoners;
                                if (GetUnseenForeignChanges(metadata, out foreignNewbies, out foreignDirtballs, out foreignGoners))
                                {
                                    var newObjects     = new HashSet <ICmObjectOrSurrogate>(foreignNewbies);
                                    var editedObjects  = new HashSet <ICmObjectOrSurrogate>(foreignDirtballs);
                                    var removedObjects = new HashSet <ICmObjectId>(foreignGoners);

                                    IEnumerable <CustomFieldInfo> fields;
                                    if (HaveAnythingToCommit(newObjects, editedObjects, removedObjects, out fields) && (StartupVersionNumber == ModelVersion))
                                    {
                                        base.WriteCommitWork(new CommitWork(newObjects, editedObjects, removedObjects, fields));
                                    }
                                }
                                // XML file is now totally up-to-date
                                metadata.FileGeneration = metadata.CurrentGeneration;
                            }
                            RemovePeer(metadata, m_peerID);
#if __MonoCS__
                            delete = metadata.Peers.Count == 0;
#endif
                            SaveMetadata(stream, metadata);
                        }
                    }

                    base.UnlockProject();

                    m_commitLog.Dispose();
                    m_commitLog = null;

                    m_commitLogMetadata.Dispose();
                    m_commitLogMetadata = null;

#if __MonoCS__
                    if (delete)
                    {
                        File.Delete(Path.Combine(m_commitLogDir, CommitLogMetadataName));
                        File.Delete(Path.Combine(m_commitLogDir, CommitLogName));
                        m_commitLogMutex.Unlink();
                    }
#endif
                }
            }

            if (m_commitLogMutex != null)
            {
                m_commitLogMutex.Dispose();
                m_commitLogMutex = null;
            }

            if (CommitThread != null)
            {
                CommitThread.Stop();
                CommitThread.Dispose();
                CommitThread = null;
            }

            foreach (Process peerProcess in m_peerProcesses.Values)
            {
                peerProcess.Close();
            }
            m_peerProcesses.Clear();
        }