예제 #1
0
        public ServerInfo InsertOrUpdate(ServerRegistration registration)
        {
            var currentTime = DateTimeOffset.Now;

            ServerInfo host;

            lock (this.serverTable)
            {
                if (!this.serverTable.TryGetValue(registration.Hostname, out host))
                {
                    Events.Write.AddedRemoteHost(registration.Hostname, registration.Port);
                    host = new ServerInfo(registration);
                    this.serverTable[registration.Hostname] = host;

                    host.LatestCounterTimeUpdated +=
                        (server, counterName, timestamp) =>
                    {
                        if (this.LatestCounterTimeUpdated != null)
                        {
                            this.LatestCounterTimeUpdated(server, counterName, timestamp);
                        }
                    };
                }
            }
            host.LastUpdateTime = currentTime;

            return(host);
        }
예제 #2
0
        /// <summary>
        /// Called to 'call home' to ensure the current server has an active record
        /// </summary>
        /// <param name="address"></param>
        public void EnsureActive(string address)
        {
            var uow = _uowProvider.GetUnitOfWork();

            using (var repo = _repositoryFactory.CreateServerRegistrationRepository(uow))
            {
                //NOTE: we cannot use Environment.MachineName as this does not work in medium trust
                // found this out in CDF a while back: http://clientdependency.codeplex.com/workitem/13191

                var computerName = System.Net.Dns.GetHostName();
                var query        = Query <ServerRegistration> .Builder.Where(x => x.ComputerName.ToUpper() == computerName.ToUpper());

                var found = repo.GetByQuery(query).ToArray();
                ServerRegistration server;
                if (found.Any())
                {
                    server = found.First();
                    server.ServerAddress = address;         //This should not  really change but it might!
                    server.UpdateDate    = DateTime.UtcNow; //Stick with Utc dates since these might be globally distributed
                    server.IsActive      = true;
                }
                else
                {
                    server = new ServerRegistration(address, computerName, DateTime.UtcNow);
                }
                repo.AddOrUpdate(server);
                uow.Commit();
            }
        }
        public async Task StartExecuteReturnsOkAndAddsHandlerIfPayloadIsValid()
        {
            var message = new ServerRegistration
            {
                Hostname = "testServer",
                Port     = 867,
            };
            ByteArrayContent payload;

            using (var ms = new MemoryStream())
                using (var writerStream = new WriterStream(ms))
                {
                    writerStream.CreateCompactBinaryWriter().Write(message);
                    payload = new ByteArrayContent(ms.GetBuffer());
                }

            var response = await
                           this.httpClient.PostAsync(TestUtils.GetUri(this.server,
                                                                      RegistrationClient.RegistrationEndpoint,
                                                                      string.Empty),
                                                     payload);

            Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
            Assert.IsNotNull(this.server.ServerList["testServer"]);
        }
예제 #4
0
    public static ServerRegistration BuildEntity(ServerRegistrationDto dto)
    {
        var model = new ServerRegistration(dto.Id, dto.ServerAddress, dto.ServerIdentity, dto.DateRegistered, dto.DateAccessed, dto.IsActive, dto.IsSchedulingPublisher);

        // reset dirty initial properties (U4-1946)
        model.ResetDirtyProperties(false);
        return(model);
    }
예제 #5
0
        private async void StartRegistration()
        {
            IPAddress[] addresses;
            try
            {
                addresses =
                    await Task <IPAddress[]> .Factory.FromAsync(Dns.BeginGetHostAddresses, Dns.EndGetHostAddresses,
                                                                this.destinationHostname, null);
            }
            catch (SocketException e)
            {
                Events.Write.RegistrationDestinationResolutionFailed(this.destinationHostname, e.Message);
                return;
            }

            var serverRegistration = new ServerRegistration
            {
                Hostname        = this.sourceHostname,
                Port            = this.sourcePort,
                MachineFunction = this.sourceMachineFunction,
                Datacenter      = this.sourceDatacenter,
            };

            foreach (var counter in this.dataManager.Counters)
            {
                serverRegistration.Counters.Add(
                    new CounterInfo
                {
                    Name       = counter.Name,
                    Type       = counter.Type,
                    Dimensions = counter.Dimensions.ToList(),
                    StartTime  = counter.StartTime.ToMillisecondTimestamp(),
                    EndTime    = counter.EndTime.ToMillisecondTimestamp(),
                });
            }

            byte[] payload;
            using (var ms = new MemoryStream())
                using (var writerStream = new WriterStream(ms, this.dataManager.MemoryStreamManager))
                {
                    var writer = writerStream.CreateCompactBinaryWriter();
                    writer.Write(serverRegistration);
                    payload = ms.ToArray();
                }

            foreach (var address in addresses)
            {
                this.RegisterWithAddress(address, payload);
            }

            lock (this)
            {
                if (this.registrationTimer != null)
                {
                    this.registrationTimer.Change(this.registrationInterval, TimeSpan.Zero);
                }
            }
        }
        public ServerRegistration BuildEntity(ServerRegistrationDto dto)
        {
            var model = new ServerRegistration(dto.Id, dto.ServerAddress, dto.ServerIdentity, dto.DateRegistered, dto.DateAccessed, dto.IsActive, dto.IsMaster);

            //on initial construction we don't want to have dirty properties tracked
            // http://issues.umbraco.org/issue/U4-1946
            model.ResetDirtyProperties(false);
            return(model);
        }
        public void Cannot_Add_Duplicate_Server_Identities()
        {
            // Arrange
            IScopeProvider provider = ScopeProvider;

            using (provider.CreateScope())
            {
                ServerRegistrationRepository repository = CreateRepository(provider);

                var server = new ServerRegistration("http://shazwazza.com", "COMPUTER1", DateTime.Now);

                Assert.That(() => repository.Save(server), Throws.InstanceOf <DbException>());
            }
        }
예제 #8
0
        public void Cannot_Add_Duplicate_Server_Identities()
        {
            // Arrange
            var provider = TestObjects.GetScopeProvider(Logger);

            using (var scope = ScopeProvider.CreateScope())
            {
                var repository = CreateRepository(provider);

                var server = new ServerRegistration("http://shazwazza.com", "COMPUTER1", DateTime.Now);

                Assert.Throws <SqlCeException>(() => repository.Save(server));
            }
        }
예제 #9
0
        public void ProcessRegistrationMessage(ServerRegistration message)
        {
            // These can change over time so go ahead and update.
            this.Port            = message.Port;
            this.MachineFunction = message.MachineFunction;
            this.Datacenter      = message.Datacenter;

            foreach (var counter in message.Counters)
            {
                var updated = false;
                var endTime = counter.EndTime.ToDateTimeOffset();
                if (endTime == DateTimeOffset.MinValue)
                {
                    continue;
                }

                this.CounterInfo.AddOrUpdate(counter,
                                             info =>
                {
                    updated = true;
                    return(endTime);
                },
                                             (info, current) =>
                {
                    if (endTime > current)
                    {
                        updated = true;
                        return(endTime);
                    }

                    if (endTime < current)
                    {
                        Events.Write.ServerLatestDataNowEarlier(this.Hostname, info.Name,
                                                                current.ToString("o"),
                                                                endTime.ToString("o"));
                    }
                    return(current);
                });

                if (updated)
                {
                    if (this.LatestCounterTimeUpdated != null)
                    {
                        this.LatestCounterTimeUpdated(this, counter.Name, endTime);
                    }

                    Events.Write.ServerLatestDataUpdated(this.Hostname, counter.Name, endTime);
                }
            }
        }
예제 #10
0
        public void ProcessRegistrationMessage(ServerRegistration message)
        {
            // These can change over time so go ahead and update.
            this.Port = message.Port;
            this.MachineFunction = message.MachineFunction;
            this.Datacenter = message.Datacenter;

            foreach (var counter in message.Counters)
            {
                var updated = false;
                var endTime = counter.EndTime.ToDateTimeOffset();
                if (endTime == DateTimeOffset.MinValue)
                {
                    continue;
                }

                this.CounterInfo.AddOrUpdate(counter,
                                             info =>
                                             {
                                                 updated = true;
                                                 return endTime;
                                             },
                                             (info, current) =>
                                             {
                                                 if (endTime > current)
                                                 {
                                                     updated = true;
                                                     return endTime;
                                                 }

                                                 if (endTime < current)
                                                 {
                                                     Events.Write.ServerLatestDataNowEarlier(this.Hostname, info.Name,
                                                                                             current.ToString("o"),
                                                                                             endTime.ToString("o"));
                                                 }
                                                 return current;
                                             });

                if (updated)
                {
                    if (this.LatestCounterTimeUpdated != null)
                    {
                        this.LatestCounterTimeUpdated(this, counter.Name, endTime);
                    }

                    Events.Write.ServerLatestDataUpdated(this.Hostname, counter.Name, endTime);
                }
            }
        }
예제 #11
0
        public void Cannot_Add_Duplicate_Computer_Names()
        {
            // Arrange
            var provider   = new PetaPocoUnitOfWorkProvider();
            var unitOfWork = provider.GetUnitOfWork();

            // Act
            using (var repository = new ServerRegistrationRepository(unitOfWork))
            {
                var server = new ServerRegistration("http://shazwazza.com", "COMPUTER1", DateTime.Now);
                repository.AddOrUpdate(server);

                Assert.Throws <SqlCeException>(unitOfWork.Commit);
            }
        }
        /// <summary>
        /// Touches a server to mark it as active; deactivate stale servers.
        /// </summary>
        /// <param name="serverAddress">The server url.</param>
        /// <param name="serverIdentity">The server unique identity.</param>
        /// <param name="staleTimeout">The time after which a server is considered stale.</param>
        public void TouchServer(string serverAddress, string serverIdentity, TimeSpan staleTimeout)
        {
            using (var scope = ScopeProvider.CreateScope())
            {
                scope.WriteLock(Constants.Locks.Servers);

                ((ServerRegistrationRepository)_serverRegistrationRepository).ClearCache();  // ensure we have up-to-date cache

                var regs      = _serverRegistrationRepository.GetMany().ToArray();
                var hasMaster = regs.Any(x => ((ServerRegistration)x).IsMaster);
                var server    = regs.FirstOrDefault(x => x.ServerIdentity.InvariantEquals(serverIdentity));

                if (server == null)
                {
                    server = new ServerRegistration(serverAddress, serverIdentity, DateTime.Now);
                }
                else
                {
                    server.ServerAddress = serverAddress; // should not really change but it might!
                    server.UpdateDate    = DateTime.Now;
                }

                server.IsActive = true;
                if (hasMaster == false)
                {
                    server.IsMaster = true;
                }

                _serverRegistrationRepository.Save(server);
                _serverRegistrationRepository.DeactiveStaleServers(staleTimeout); // triggers a cache reload

                // reload - cheap, cached
                // reload - cheap, cached

                // default role is single server, but if registrations contain more
                // than one active server, then role is master or replica
                regs = _serverRegistrationRepository.GetMany().ToArray();

                // default role is single server, but if registrations contain more
                // than one active server, then role is master or replica
                _currentServerRole = regs.Count(x => x.IsActive) > 1
                    ? (server.IsMaster ? ServerRole.Master : ServerRole.Replica)
                    : ServerRole.Single;

                scope.Complete();
            }
        }
예제 #13
0
    /// <summary>
    ///     Touches a server to mark it as active; deactivate stale servers.
    /// </summary>
    /// <param name="serverAddress">The server URL.</param>
    /// <param name="staleTimeout">The time after which a server is considered stale.</param>
    public void TouchServer(string serverAddress, TimeSpan staleTimeout)
    {
        var serverIdentity = GetCurrentServerIdentity();

        using (ICoreScope scope = ScopeProvider.CreateCoreScope())
        {
            scope.WriteLock(Constants.Locks.Servers);

            _serverRegistrationRepository.ClearCache(); // ensure we have up-to-date cache

            IServerRegistration[]? regs = _serverRegistrationRepository.GetMany()?.ToArray();
            var hasSchedulingPublisher = regs?.Any(x => ((ServerRegistration)x).IsSchedulingPublisher);
            IServerRegistration?server =
                regs?.FirstOrDefault(x => x.ServerIdentity?.InvariantEquals(serverIdentity) ?? false);

            if (server == null)
            {
                server = new ServerRegistration(serverAddress, serverIdentity, DateTime.Now);
            }
            else
            {
                server.ServerAddress = serverAddress; // should not really change but it might!
                server.UpdateDate    = DateTime.Now;
            }

            server.IsActive = true;
            if (hasSchedulingPublisher == false)
            {
                server.IsSchedulingPublisher = true;
            }

            _serverRegistrationRepository.Save(server);
            _serverRegistrationRepository.DeactiveStaleServers(staleTimeout); // triggers a cache reload

            // reload - cheap, cached
            regs = _serverRegistrationRepository.GetMany().ToArray();

            // default role is single server, but if registrations contain more
            // than one active server, then role is scheduling publisher or subscriber
            _currentServerRole = regs.Count(x => x.IsActive) > 1
                ? server.IsSchedulingPublisher ? ServerRole.SchedulingPublisher : ServerRole.Subscriber
                : ServerRole.Single;

            scope.Complete();
        }
    }
예제 #14
0
        public void NoOuterScopeJustWorks()
        {
            var uowProvider = new PetaPocoUnitOfWorkProvider(Logger);
            var sqlSyntax   = ApplicationContext.DatabaseContext.SqlSyntax;

            var lrepo = new LockingRepository <IServerRegistrationRepository>(uowProvider,
                                                                              x => CreateRepository(x, Logger, CacheHelper, sqlSyntax),
                                                                              new[] { Constants.Locks.Servers }, new[] { Constants.Locks.Servers });

            IServerRegistration reg = null;

            lrepo.WithWriteLocked(xrepo =>
            {
                xrepo.Repository.AddOrUpdate(reg = new ServerRegistration("a1234", "i1234", DateTime.Now));

                // no need - autocommit by default
                //xrepo.UnitOfWork.Commit();
            });

            Assert.IsNull(((ScopeProvider)ApplicationContext.ScopeProvider).AmbientScope);

            Assert.AreNotEqual(0, reg.Id);

            // that's cheating somehow because it will not really hit the DB because of the cache
            var reg2 = lrepo.WithReadLocked(xrepo =>
            {
                return(xrepo.Repository.Get(reg.Id));
            });

            Assert.IsNull(((ScopeProvider)ApplicationContext.ScopeProvider).AmbientScope);

            Assert.IsNotNull(reg2);
            Assert.AreEqual("a1234", reg2.ServerAddress);
            Assert.AreEqual("i1234", reg2.ServerIdentity);

            // this really makes sure there's something in database
            using (var scope = ApplicationContext.ScopeProvider.CreateScope())
            {
                var reg3 = scope.Database.Fetch <dynamic>("SELECT * FROM umbracoServer WHERE id=@id", new { id = reg2.Id }).FirstOrDefault();
                Assert.IsNotNull(reg3);
                Assert.AreEqual("a1234", reg3.address);
                Assert.AreEqual("i1234", reg3.computerName);
            }

            Assert.IsNull(((ScopeProvider)ApplicationContext.ScopeProvider).AmbientScope);
        }
예제 #15
0
        public void Can_Perform_Add_On_Repository()
        {
            // Arrange
            var provider   = new PetaPocoUnitOfWorkProvider();
            var unitOfWork = provider.GetUnitOfWork();

            using (var repository = new ServerRegistrationRepository(unitOfWork))
            {
                // Act
                var server = new ServerRegistration("http://shazwazza.com", "COMPUTER4", DateTime.Now);
                repository.AddOrUpdate(server);
                unitOfWork.Commit();

                // Assert
                Assert.That(server.HasIdentity, Is.True);
                Assert.That(server.Id, Is.EqualTo(4));//With 3 existing entries the Id should be 4
            }
        }
예제 #16
0
        public ServerInfo(ServerRegistration registration)
        {
            if (string.IsNullOrEmpty(registration.Hostname))
            {
                throw new ArgumentException("No hostname provided.", "registration.Hostname");
            }
            if (registration.Port == 0)
            {
                throw new ArgumentOutOfRangeException("registration.Port");
            }

            this.Hostname = registration.Hostname;
            this.Port = registration.Port;
            this.MachineFunction = registration.MachineFunction;
            this.Datacenter = registration.Datacenter;
            this.lastUpdateTime = DateTimeOffset.MinValue;
            this.CounterInfo = new ConcurrentDictionary<CounterInfo, DateTimeOffset>();
        }
        public void Can_Perform_Add_On_Repository()
        {
            // Arrange
            IScopeProvider provider = ScopeProvider;

            using (provider.CreateScope())
            {
                ServerRegistrationRepository repository = CreateRepository(provider);

                // Act
                var server = new ServerRegistration("http://shazwazza.com", "COMPUTER4", DateTime.Now);
                repository.Save(server);

                // Assert
                Assert.That(server.HasIdentity, Is.True);
                Assert.That(server.Id, Is.EqualTo(4)); // With 3 existing entries the Id should be 4
            }
        }
예제 #18
0
        public ServerInfo(ServerRegistration registration)
        {
            if (string.IsNullOrEmpty(registration.Hostname))
            {
                throw new ArgumentException("No hostname provided.", "registration.Hostname");
            }
            if (registration.Port == 0)
            {
                throw new ArgumentOutOfRangeException("registration.Port");
            }

            this.Hostname        = registration.Hostname;
            this.Port            = registration.Port;
            this.MachineFunction = registration.MachineFunction;
            this.Datacenter      = registration.Datacenter;
            this.lastUpdateTime  = DateTimeOffset.MinValue;
            this.CounterInfo     = new ConcurrentDictionary <CounterInfo, DateTimeOffset>();
        }
예제 #19
0
        /// <summary>
        /// Touches a server to mark it as active; deactivate stale servers.
        /// </summary>
        /// <param name="serverAddress">The server url.</param>
        /// <param name="serverIdentity">The server unique identity.</param>
        /// <param name="staleTimeout">The time after which a server is considered stale.</param>
        public void TouchServer(string serverAddress, string serverIdentity, TimeSpan staleTimeout)
        {
            _lrepo.WithWriteLocked(xr =>
            {
                ((ServerRegistrationRepository)xr.Repository).ReloadCache();  // ensure we have up-to-date cache

                var regs      = xr.Repository.GetAll().ToArray();
                var hasMaster = regs.Any(x => ((ServerRegistration)x).IsMaster);
                var server    = regs.FirstOrDefault(x => x.ServerIdentity.InvariantEquals(serverIdentity));

                if (server == null)
                {
                    server = new ServerRegistration(serverAddress, serverIdentity, DateTime.Now);
                }
                else
                {
                    server.ServerAddress = serverAddress; // should not really change but it might!
                    server.UpdateDate    = DateTime.Now;
                }

                server.IsActive = true;
                if (hasMaster == false)
                {
                    server.IsMaster = true;
                }

                xr.Repository.AddOrUpdate(server);
                xr.UnitOfWork.Commit();                           // triggers a cache reload
                xr.Repository.DeactiveStaleServers(staleTimeout); // triggers a cache reload

                // reload - cheap, cached
                regs = xr.Repository.GetAll().ToArray();

                // default role is single server, but if registrations contain more
                // than one active server, then role is master or replica
                _currentServerRole = regs.Count(x => x.IsActive) > 1
                    ? (server.IsMaster ? ServerRole.Master : ServerRole.Slave)
                    : ServerRole.Single;
            });
        }
        public async Task StartExecuteReturnsOkAndAddsHandlerIfPayloadIsValid()
        {
            var message = new ServerRegistration
                          {
                              Hostname = "testServer",
                              Port = 867,
                          };
            ByteArrayContent payload;
            using (var ms = new MemoryStream())
            using (var writerStream = new WriterStream(ms))
            {
                writerStream.CreateCompactBinaryWriter().Write(message);
                payload = new ByteArrayContent(ms.GetBuffer());
            }

            var response = await
                           this.httpClient.PostAsync(TestUtils.GetUri(this.server,
                                                                      RegistrationClient.RegistrationEndpoint,
                                                                      string.Empty),
                                                     payload);
            Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
            Assert.IsNotNull(this.server.ServerList["testServer"]);
        }
예제 #21
0
        private async void StartRegistration()
        {
            IPAddress[] addresses;
            try
            {
                addresses =
                    await Task<IPAddress[]>.Factory.FromAsync(Dns.BeginGetHostAddresses, Dns.EndGetHostAddresses,
                                                              this.destinationHostname, null);
            }
            catch (SocketException e)
            {
                Events.Write.RegistrationDestinationResolutionFailed(this.destinationHostname, e.Message);
                return;
            }

            var serverRegistration = new ServerRegistration
                                     {
                                         Hostname = this.sourceHostname,
                                         Port = this.sourcePort,
                                         MachineFunction = this.sourceMachineFunction,
                                         Datacenter = this.sourceDatacenter,
                                     };

            foreach (var counter in this.dataManager.Counters)
            {
                serverRegistration.Counters.Add(
                                                new CounterInfo
                                                {
                                                    Name = counter.Name,
                                                    Type = counter.Type,
                                                    Dimensions = counter.Dimensions.ToList(),
                                                    StartTime = counter.StartTime.ToMillisecondTimestamp(),
                                                    EndTime = counter.EndTime.ToMillisecondTimestamp(),
                                                });
            }

            byte[] payload;
            using (var ms = new MemoryStream())
            using (var writerStream = new WriterStream(ms, this.dataManager.MemoryStreamManager))
            {
                var writer = writerStream.CreateCompactBinaryWriter();
                writer.Write(serverRegistration);
                payload = ms.ToArray();
            }

            foreach (var address in addresses)
            {
                this.RegisterWithAddress(address, payload);
            }

            lock (this)
            {
                if (this.registrationTimer != null)
                {
                    this.registrationTimer.Change(this.registrationInterval, TimeSpan.Zero);
                }
            }
        }
예제 #22
0
 public void LoadServerPlugins()
 {
     LoadGlobalPlugins();
     ServerRegistration.GetInstance();
 }