Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Save more on your purchases! discount-offer-chevron-icon
Savings automatically calculated. No voucher code required.
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Events
Videos
Audiobooks
Packt Hub
Free Learning
Arrow right icon
timer SALE ENDS IN
0 Days
:
00 Hours
:
00 Minutes
:
00 Seconds

How-To Tutorials

7018 Articles
article-image-devops-tools-and-technologies
Packt
11 Nov 2016
15 min read
Save for later

DevOps Tools and Technologies

Packt
11 Nov 2016
15 min read
In this article by Ritesh Modi, the author of the book DevOps with Windows Server 2016, we will introduce foundational platforms and technologies instrumental in enabling and implementing DevOps practices. (For more resources related to this topic, see here.) These include: Technology stack for implementing Continuous Integration, Continuous Deployment, Continuous Deliver, Configuration Management, and Continuous Improvement. These form the backbone for DevOps processes and include source code services, build services, and release services through Visual Studio Team Services. Platform and technology used to create and deploy a sample web application. This includes technologies such as Microsoft .NET, ASP.NET and SQL Server databases. Tools and technology for configuration management, testing of code and application, authoring infrastructure as code, and deployment of environments. Examples of these tools and technologies are Pester for environment validation, environment provisioning through Azure Resource Manager (ARM) templates, Desired State Configuration (DSC) and Powershell, application hosting on containers through Windows Containers and Docker, application and database deployment through Web Deploy packages, and SQL Server bacpacs. Cloud technology Cloud is ubiquitous. Cloud is used for our development environment, implementation of DevOps practices, and deployment of applications. Cloud is a relatively new paradigm in infrastructure provisioning, application deployment, and hosting space. The only options prior to the advent of cloud was either self-hosted on-premises deployments or using services from a hosting service provider. However, cloud is changing the way enterprises look at their strategy in relation to infrastructure and application development, deployment, and hosting. In fact, the change is so enormous that it has found its way into every aspect of an organization's software development processes, tools, and practices. Cloud computing refers to the practice of deploying applications and services on the Internet with a cloud provider. A cloud provider provides multiple types of services on cloud. They are divided into three categories based on their level of abstraction and degree of control on services. These categories are as follows: Infrastructure as a Service (IaaS) Platform as a Service (PaaS) Software as a Service (SaaS) These three categories differ based on the level of control a cloud provider exercises compared to the cloud consumer. The services provided by a cloud provider can be divided into layers, with each layer providing a type of service. As we move higher in the stack of layers, the level of abstraction increases in line with the cloud provider's control over services. In other words, the cloud consumer starts to lose control over services as you move higher in each column: Figure 1: Cloud Services – IaaS, PaaS and SaaS Figure 1 shows the three types of service available through cloud providers and the layers that comprise these services. These layers are stacked vertically on each other and show the level of control a cloud provider has compared to a consumer. From Figure 1, it is clear that for IaaS, a cloud provider is responsible for providing, controlling, and managing layers from the network layer up to the virtualization layer. Similarly, for PaaS, a cloud provider controls and manages from the hardware layer up to the runtime layer, while the consumer controls only the application and data layers. Infrastructure as a Service (IaaS) As the name suggests, Infrastructure as a Service is an infrastructure service provided by a cloud provider. This service includes the physical hardware and its configuration, network hardware and its configuration, storage hardware and its configuration, load balancers, compute, and virtualization. Any layer above virtualization is the responsibility of the consumer to provision, configure, and manage. The consumer can decide to use the provided underlying infrastructure in whatever way best suits their requirements. Consumers can consume the storage, network, and virtualization to provision their virtual machines on top of. It is the consumer's responsibility to manage and control the virtual machines and the things deployed within it. Platform as a Service (PaaS) Platform as a Service enables consumers to deploy their applications and services on the provided platform, consuming the underlying runtime, middleware, and services. The cloud provider provides the services from infrastructure to runtime. The consumers cannot provision virtual machines as they cannot access and control them. Instead, they can only control and manage their applications. This is a comparatively faster method of development and deployment because now the consumer can focus on application development and deployment. Examples of Platform as a Service include Azure Automation, Azure SQL, and Azure App Services. Software as a Service (SaaS) Software as a Service provides complete control of the service to the cloud provider. The cloud provider provisions, configures, and manages everything from infrastructure to the application. It includes the provisioning of infrastructure, deployment and configuration of applications, and provides application access to the consumer. The consumer does not control and manage the application, and can use and configure only parts of the application. They control only their data and configuration. Generally, multi-tenant applications used by multiple consumers, such as Office 365 and Visual Studio Team Services, are examples of SaaS. Advantages of using cloud computing There are multiple distinct advantages of using cloud technologies. The major among them are as follows: Cost effective: Cloud computing helps organizations to reduce the cost of storage, networks, and physical infrastructure. It also prevents them from having to buy expensive software licenses. The operational cost of managing these infrastructures also reduces due to lesser effort and manpower requirements. Unlimited capacity: Cloud provides unlimited resources to the consumer. This ensures applications will never get throttled due to limited resource availability. Elasticity: Cloud computing provides the notion of unlimited capacity and applications deployed on it can scale up or down on an as-needed basis. When demand for the application increases, cloud can be configured to scale up the infrastructure and application by adding additional resources. At the same time, it can scale down unnecessary resources during periods of low demand. Pay as you go: Using cloud eliminates capital expenditure and organizations pay only for what they use, thereby providing maximum return on investment. Organizations do not need to build additional infrastructure to host their application for times of peak demand. Faster and better: Cloud provides ready-to-use applications and faster provisioning and deployment of environments. Moreover, organizations get better-managed services from their cloud provider with higher service-level agreements. We will use Azure as our preferred cloud computing provider for the purpose of demonstrating samples and examples. However, you can use any cloud provider that provides complete end-to-end services for DevOps. We will use multiple features and services provided by Azure across IaaS and PaaS. We will consume Operational Insights and Application Insights to monitor our environment and application, which will help capture relevant telemetry for auditing purposes. We will provision Azure virtual machines running Windows and Docker Containers as a hosting platform. We will use Windows Server 2016 as the target operating system for our applications on cloud. Azure Resource Manager (ARM). We will also use Desired State Configuration and PowerShell as our configuration management platform and tool. We will use Visual Studio Team Services (VSTS), a suite of PaaS services on cloud provided by Microsoft, to set up and implement our end-to-end DevOps practices. Microsoft also provides the same services as part of Team Foundation Services (TFS) as an on-premises solution. Technologies like Pester, DSC, and PowerShell can be deployed and configured to run on any platform. These will help both in the validation of our environment and in the configuration of both application and environment, as part of our Configuration management process. Windows Server 2016 is a breakthrough operating system from Microsoft also referred to as Cloud Operating System. We will look into Windows Server 2016 in the following section. Windows Server 2016 Windows Server 2016 has come a long way. All the way from Windows NT to Windows 2000 and 2003, then Windows 2008 (R2) and 2012 (R2), and now Windows Server 2016. Windows NT was the first popular Windows server among enterprises. However, the true enterprise servers were Windows 2000 and Windows 2003. The popularity of Windows Server 2003 was unprecedented and it was widely adopted. With Windows Server 2008 and 2008 R2, the idea of the data center took priority and enterprises with their own data center adopted it. Even the Windows Server 2008 series was quite popular among enterprises. In 2010, the Microsoft cloud, Azure, was launched. The first steps towards a cloud operating system were Windows Server 2012 and 2012 R2. They had the blueprints and technology to be seamlessly provisioned on Azure. Now, when Azure and cloud are gaining enormous popularity, Windows Server 2016 is released as a true cloud operating system. The evolution of Windows Server is shown in Figure 2: Figure 2: Windows Server evolution Windows Server 2016 is referred to as a cloud operating system. It is built with cloud in mind. It is also referred to as the first operating system that enables DevOps seamlessly by providing relevant tools and technologies. It makes implementing DevOps simpler and easier through its productivity tools. Let us look briefly into these tools and technologies. Multiple choices for Application platform Windows Server 2016 comes with many choices for application platform for applications. It provides the following: Windows Server 2016 Nano Server Windows and Docker Containers Hyper-V Containers Nested virtual machines Windows Server as a hosting platform Windows server 2016 can be used in the ways it has always been used, such as hosting applications and providing server functionalities. It provides the services necessary to make applications secure, scalable, and highly available. It also provides virtualization, directory services, certificate services, web server, databases, and more. These services can be consumed by the enterprise’s services and applications. Nano Server Windows Server provides a new option to host applications and services. This is a new variety of lightweight, scaled-down Windows server containing only the kernel and drivers necessary to run as an operating system. They are also known as headless servers. They do not have any graphical user interface and the only way to interact and manage them is through remote PowerShell. Out of the box, they do not contain any service or feature. The services need to be added to Nano servers explicitly before use. So far, they are the most secure servers from Microsoft. They are very lightweight and their resource requirements and consumption is less than 80% of a normal Windows server. The number of services running, the number of ports open, the number of processes running and the amount of memory and storage required, also are less than 80% compared to normal Windows server. Even though Nano Server out of box just has the kernel and drivers, its capabilities can be enhanced by adding features and deploying any Windows application on it. Windows Containers and Docker Containers are one of the most revolutionary features added to Windows Server 2016 after Nano Server. With the popularity and adoption of Docker Containers, which primarily run on Linux, Microsoft decided to introduce container services to Windows Server 2016. Containers are operating system virtualization. This means that multiple containers can be deployed on the same operating system and each one of them will share the host operating system kernel. It is the next level of virtualization after server virtualization (virtual machines). Containers generate the notion of complete operating system isolation and independence, even though it uses the same host operating system underneath it. This is possible through the use of namespace isolation and image layering. Containers are created from images. Images are immutable and cannot be modified. Each image has a base operating system and a series of instructions that are executed against it. Each instruction creates a new image on top of the previous image and contains only the modification. Finally, a writable image is stacked on top of these images. These images are combined into a single image, which can then be used for provisioning containers. A container made up of multiple image layers is shown in Figure 3: Figure 3: Containers made up of multiple image layers Namespace isolation helps provide containers with pristine new environments. The containers cannot see the host resources and the host cannot view the container resources. For the application within the container, a complete new installation of the operating system is available. The containers share the host's memory, CPU, and storage. Containers offer operating system virtualization, which means the containers can host only those operating systems supported by the host operating system. There cannot be a Windows container running on a Linux host, and a Linux container cannot run on a Windows host operating system. Hyper-V containers Another type of container technology Windows Server 2016 provides is Hyper-V Containers. These containers are similar to Windows Containers. They are managed through the same Docker client and extend the same Docker APIs. However, these containers contain their own scaled down operating system kernel. They do not share the host operating system but have their own dedicated operating system, and their own dedicated memory and CPU assigned in exactly the same way virtual machines are assigned resources. Hyper-V Containers brings in a higher level of isolation of containers from the host. While Windows Containers runs in full trust on the host operating system, Hyper-V Containers does not have full trust from the host’s perspective. It is this isolation that differentiates Hyper-V Containers from Windows Containers. Hyper-V Containers is ideal for hosting applications that might harm the host server affecting every other container and service on it. Scenarios where users can bring in and execute their own code are examples of such applications. Hyper-V Containers provides adequate isolation and security to ensure that applications cannot access the host resources and change them. Nested virtual machines Another breakthrough innovation of Windows Server 2016 is that now, virtual machines can host virtual machines. Now, we can deploy multiple virtual machines containing all tiers of an application within a single virtual machine. This is made possible through software-defined networks and storage. Enabling Microservices Nano Servers and Containers helps provide advanced lightweight deployment options through which we can now decompose the entire application into multiple smaller, independent services, each with their own scalability and high availability configuration, and deploy them independently of each other. Microservices helps in making the entire DevOps lifecycle agile. With Microservices, changes to services do not demand that every other Microservices undergo every test validation. Only the changed service needs to be tested rigorously, along with its integration with other services. Compare this to a monolithic application. Even a single small change will result in having to test the entire application. Microservices helps in that it requires smaller teams for its development, testing of a service can happen independently of other services, and deployment can be done for each service in isolation. Continuous Integration, Continuous Deployment, and Continuous Delivery for each service can be executed in isolation rather than compiling, testing, and deploying the whole application every time there is a change. Reduced maintenance Because of their intrinsic nature, Windows Nano Servers and Containers are lightweight and quick to provision. They help to quickly provision and configure environments, thereby reducing the overall time needed for Continuous Integration and deployment. Also, these resources can be provisioned on Azure on-demand without waiting for hours. Because of their small footprint in terms of size, storage, memory, and features, they need less maintenance. These servers are patched less often, with fewer fixes, they are secure by default, and have less chance of failing applications, which makes them ideal for operations. The operations team needs to spend fewer hours maintaining these servers compared to normal servers. This reduces the overall cost for the organization and helps DevOps ensure a high-quality delivery. Configuration management tools Windows Server 2016 comes with Windows Management Framework 5.0 installed by default. Desired State Configuration (DSC) is the new configuration management platform available out of the box in Windows Server 2016. It has a rich, mature set of features that enables configuration management for both environments and applications. With DSC, the desired state and configuration of environments are authored as part of Infrastructure as Code and executed on every server on a scheduled basis. They help check the current state of servers with the documented desired state and bring them back to the desired state. DSC is available as part of PowerShell and PowerShell helps with authoring these configuration documents. Windows server 2016 provides a PowerShell unit testing framework known as PESTER. Historically, unit testing for infrastructure environments was always missing as a feature. PESTER enables the testing of infrastructure provisioned either manually or through Infrastructure as Code using DSC configuration or ARM templates. These help with the operational validation of the entire environment, bringing in a high level of cadence and confidence in Continuous Integration and deployment processes. Deployment and packaging Package management and the deployment of utilities and tools through automation is a new concept in the Windows world. Package management has been ubiquitous in the Linux world for a long time. Packing management helps search, save, install, deploy, upgrade, and remove software packages from multiple sources and repositories on demand. There are public repositories such as Chocolatey and PSGallery available for storing readily deployable packages. Tools such as NuGet can connect these repositories and help with package management. They also help with the versioning of packages. Applications that rely on a specific package version can download it on an as-needed basis. Package management helps with the building of environments and application deployment. Package deployment is much easier and faster with this out-of-the-box Windows feature. Summary We have covered a lot of ground in this article. DevOps concepts were discussed mapping technology to those concepts. In this we saw the impetus DevOps can get from technology. We looked at cloud computing and the different services provided by cloud providers. From there, we went on to look at the benefits Windows Server 2016 brings to DevOps practices and how Windows Server 2016 makes DevOps easier and faster with its native tools and features. Resources for Article: Further resources on this subject: Introducing Dynamics CRM [article] Features of Dynamics GP [article] Creating Your First Plug-in [article]
Read more
  • 0
  • 0
  • 11686

article-image-using-proxies-monitor-remote-locations-zabbix-18
Packt
29 Mar 2010
7 min read
Save for later

Using Proxies to Monitor Remote Locations with Zabbix 1.8

Packt
29 Mar 2010
7 min read
When proxies are useful A server is not always able to connect directly to the monitored machines. We could use active items everywhere (where Zabbix agents connect to a Zabbix server, discussed in Chapter 3), but that would require access from all of the monitored hosts to the Zabbix server. Additionally, that would not work for SNMP, IPMI, and other monitoring methods. This is common when devices from other organizations have to be monitored, or when such restrictions are in place in a large corporate network. This is where Zabbix proxy comes in. When set up, only connections to the Zabbix server come from the proxy, which, in turn, does all the monitoring on behalf of the Zabbix server. In this example, there's no need for individual connections from Zabbix to individual devices in the remote location or the other way around—single firewall rule to allow Zabbix proxy connections to the Zabbix server is sufficient. So how does the proxy work? Let's repeat: Only the Zabbix proxy connects to the Zabbix serverv. This bit of information is crucial to understanding how it actually works. When the proxy connects to the server, it requests configuration information about what it has to monitor, then goes and does just that. As data is gathered, proxy sends it back to the server. Does that sound familiar? It should, because that part sounds just like an active agent, except that the proxy can gather data from different systems pretty much like the Zabbix server can. It sounds almost like a super agent. Actually, it is said that the proxy was at first internally named "super agent", which confirms the similarity. The Zabbix proxy is a very useful feature, the first stable Zabbix version to introduce it was 1.6, back in 2008. Given the usefulness of the Zabbix proxy, it is surprising that for a long time no other solutions provided something comparable. Today, Zabbix proxies continue to lead the way by having and improving features that are considered most useful for remote data collection. As we will see later, there are other benefits that proxies can provide, so let's get to actually setting one up. Setting up the proxy W hen setting up the proxy for this exercise, it is suggested you use a separate (physical or virtual) machine. If not possible, you can choose to run proxy on the same machine, as hints will be provided for such a setup as well. Before proceeding, we will have to compile the proxy itself. When compiling the proxy there are a few mandatory parameters, --enable-proxy being one. Zabbix proxy also needs a database, so you have to include support for one. While it is not suggested to use SQLite on Zabbix itself because of the performance issue, the proxy might be a good candidate. Unless it is going to monitor lots of systems, SQLite's performance can be satisfactory, and it is trivial to set up because Zabbix server creates and populates the database automatically. Additionally, Zabbix proxy must have support compiled in for things it will be monitoring, like SNMP, IPMI, and web monitoring. Let's say we want to compile Zabbix proxy with SQLite support and the ability to monitor web, SNMP, and IPMI. Obviously, we will need all the relevant support libraries mentioned when we first compiled Zabbix, but this time we'll also need another one—SQLite development headers. On most distributions they will be included in a package named sqlite-devel or similar, so make sure to install this package before proceeding. Then, on the machine where you plan to install Zabbix proxy, enter the directory where the Zabbix installation source has been extracted to and execute: $ ./configure --enable-proxy --with-sqlite3 --with-libcurl --with-netsnmp--with-openipmi && make This will both configure and compile Zabbix proxy. We can again use the simple and universal solution to create a more or less proper package by executing as root: # checkinstall --nodoc --install=yes -y --pkgname=zabbix-proxy The proxy binary is now compiled and in place, we can put our hands on the configuration now. First things first—it must be placed in the correct location: # cp misc/conf/zabbix_proxy.conf /etc/zabbix Now open /etc/zabbix/zabbix_proxy.conf as root and make some changes to get the proxy running: Hostname=proxy Hostname is an important parameter. As with active agents, if it's wrong, nothing will work. Server=<Zabbix server IP address> Zabbix proxy connects to the Zabbix server, so it must know where to connect to. DBName=/tmp/zabbix_proxy.db We will try to use an SQLite database, thus the full path to the database file must be specified. Let's try to start the Zabbix proxy now, as root execute: # zabbix_proxy Wait, we did not create the database like we did when installing the server—the proxy couldn't start up, right? Let's look at the log file—open /tmp/zabbix_proxy.log. Paying close attention we can find some interesting log records. 27982:20090729:131636.530 Cannot open database file "/tmp/zabbix_proxy.db": No such file or directory27982:20090729:131636.531 Creating database ... Wonderful. Zabbix proxy can automatically create the required SQLite database and populate it. We could also verify that Zabbix proxy is listening on the port it should be by running: $ netstat -ntl | grep 10051 The output should confirm that everything is correct. Monitoring a host through a proxy N ow that we have the proxy compiled, configured, and running, we have to inform Zabbix about it somehow. To do this, open Administration | DM in the frontend, then select Proxies in the first dropdown. No proxies are listed, so we have to create one—click the Create Proxy button and complete the form. Enter proxy in the Proxy name field. The section below; Hosts, allows us to specify which hosts will be monitored by this proxy. To make one host monitored by proxy, mark Another Host in the Other Hosts list box and click on the << button. When you are done, click Save. This server should now be monitored by the proxy, right? Again, not quite. As you might remember, we were setting the Zabbix server IP address in the agent configuration files so that agents would accept connections from these servers and send active check data to them. When we change a host to be monitored by a proxy, all connections will be made from the proxy, thus the proxy address must be added to the agent daemon's configuration file. As root, edit /etc/zabbix/zabbix_agentd.conf on Another Host and change the Hostname line to have the Zabbix proxy IP address instead of the Zabbix server IP address. Save the file, then restart the agent daemon. Now this agent will send all data to the proxy only, no connection will be made to or from Zabbix server. If, on the other hand, you have the proxy running on the same host as Zabbix server, agent will not notice that it is now queried by the proxy, not by the server, because the source IP would not have changed. The agent is still requesting and sending active checks to port 10051, Zabbix server port. To change this for the proxy port, edit /etc/zabbix/zabbix_agentd.conf on Another Host as root and change the ServerPort line to read: ServerPort=10052 Don't forget to remove the leading hash mark, then restart the agent daemon. With the host monitored solely by the proxy, let's check whether there are any indications of that in the frontend. Open Configuration | Hosts, make sure Linux servers is selected in the Group dropdown and take a look at the Name column. As can be seen, Another Host is now prefixed by the proxy name and reads proxy:Another Host. Of course, we are not limited in our proxy name choice, we could have named it "Nothing to see here" for all that the Zabbix server cares. But do we have to always go to Administration | DM whenever we want to make a host monitored by proxy? Click on Another Host in the Name column, and observe the available properties. There's one dropdown available, Monitored by proxy. Using this dropdown we can easily assign a host to be monitored by the chosen proxy (remembering to change server IP address in the agent daemon configuration file, if using active checks).
Read more
  • 0
  • 0
  • 11685

article-image-creating-routers
Packt
08 Oct 2014
11 min read
Save for later

Creating Routers

Packt
08 Oct 2014
11 min read
In this article by James Denton, author of the book, Learning OpenStack, Networking (Neutron), we will create Neutron routers and attach them to networks. The Neutron L3 agent enables IP routing and NAT support for instances within the cloud by utilizing network namespaces to provide isolated routing instances. By creating networks and attaching them to routers, tenants can expose connected instances and their applications to the Internet. The neutron-l3-agent service was installed on the controller node as part of the overall Neutron installation process. (For more resources related to this topic, see here.) Configuring the Neutron L3 agent Before the neutron-l3-agent service can be started, it must be configured. Neutron stores the L3 agent configuration in the /etc/neutron/l3_agent.ini file. The most common configuration options will be covered here. Defining an interface driver Like previously installed agents, the Neutron L3 agent must be configured to use an interface driver that corresponds to the chosen networking plugin. Using crudini, configure the Neutron L3 agent to use one of the following drivers: For LinuxBridge: # crudini --set /etc/neutron/l3_agent.ini DEFAULT interface_driver neutron.agent.linux.interface.BridgeInterfaceDriver For Open vSwitch: # crudini --set /etc/neutron/l3_agent.ini DEFAULT interface_driver neutron.agent.linux.interface.OVSInterfaceDriver Setting the external network The external network connected to a router is one that not only provides external connectivity to the router and the instances behind it, but also serves as the network from which floating IPs are derived. In Havana, each L3 agent in the cloud can be associated with only one external network. In Icehouse, L3 agents are capable of supporting multiple external networks. To be eligible to serve as an external network, a provider network must have been configured with its router:external attribute set to true. In Havana, if more than one provider network has the attribute set to true, then the gateway_external_network_id configuration option must be used to associate an external network to the agent. To define a specific external network, configure the gateway_external_network_id option as follows: gateway_external_network_id = <UUID of eligible provider network> In Havana, if this option is left empty, the agent will enforce that only a single external networks exists. The agent will automatically use the network for which the router:external attribute is set to true. The default configuration contains an empty or unset value and is sufficient for now. Setting the external bridge The L3 agent must be aware of how to connect the external interface of a router to the network. The external_network_bridge configuration option defines a bridge on the host in which the external interface will be connected. In earlier releases of Havana, the default value of external_network_bridge was br-ex, a bridge expected to be configured manually outside of OpenStack and intended to be dedicated to the external network. As a result of the bridge not being fully managed by OpenStack, provider attributes of the network created within Neutron, including the segmentation ID, network type, and the provider bridge itself, are ignored. To fully utilize a provider network and its attributes, the external_network_bridge configuration option should be set to an empty, or blank, value. By doing so, Neutron will adhere to the attributes of the network and place the external interface of routers into a bridge that it creates, along with a physical or virtual VLAN interface used to provide external connectivity. When using Open vSwitch, the external interface of the router is placed in the integration bridge and assigned to the appropriate local VLAN. With the LinuxBridge plugin, the external interface of routers is placed into a Linux bridge that corresponds to the external network. Using crudini, set the external_network_bridge configuration option to an empty value as follows: # crudini --set /etc/neutron/l3_agent.ini DEFAULT external_network_bridge Enabling the metadata proxy When Neutron routers are used as the gateway for instances, requests for metadata are proxied by the router and forwarded to the Nova metadata service. This feature is enabled by default and can be disabled by setting the enable_metadata_proxy value to false in the l3_agent.ini configuration file. Starting the Neutron L3 agent To start the neutron-l3-agent service and configure it to start at boot, issue the following commands on the controller node: # service neutron-l3-agent start # chkconfig neutron-l3-agent on Verify the agent is running: # service neutron-l3-agent status The service should return an output similar to the following: [root@controller neutron]# service neutron-l3-agent status neutron-l3-agent (pid 13501) is running... If the service remains stopped, troubleshoot any issues that may be found in the /var/log/neutron/l3-agent.log log file. Router management in the CLI Neutron offers a number of commands that can be used to create and manage routers. The primary commands associated with router management include: router-create router-delete router-gateway-clear router-gateway-set router-interface-add router-interface-delete router-list router-list-on-l3-agent router-port-list router-show router-update Creating routers in the CLI Routers in Neutron are associated with tenants and are available for use only by users within the tenant that created them. As an administrator, you can create routers on behalf of tenants during the creation process. To create a router, use the router-create command as follows: Syntax: router-create [--tenant-id TENANT_ID] [--admin-state-down] NAME Working with router interfaces in the CLI Neutron routers have two types of interfaces: gateway and internal. The gateway interface of a Neutron router is analogous to the WAN interface of a hardware router. It is the interface connected to an upstream device that provides connectivity to external resources. The internal interfaces of Neutron routers are analogous to the LAN interfaces of hardware routers. Internal interfaces are connected to tenant networks and often serve as the gateway for connected instances. Attaching internal interfaces to routers To create an interface in the router and attach it to a subnet, use the router-interface-add command as follows: Syntax: router-interface-add <router-id> <INTERFACE> In this case, INTERFACE is the ID of the subnet to be attached to the router. In Neutron, a network may contain multiple subnets. It is important to attach the router to each subnet so that it properly serves as the gateway for those subnets. Once the command is executed, Neutron creates a port in the database that is associated with the router interface. The L3 agent is responsible for connecting interfaces within the router namespace to the proper bridge. Attaching a gateway interface to a router The external interface of a Neutron router is referred to as the gateway interface. A router is limited to a single gateway interface. To be eligible for use as an external network that can be used for gateway interfaces, a provider network must have its router:external attribute set to true. To attach a gateway interface to a router, use the router-gateway-set command as follows: Syntax: router-gateway-set <router-id> <external-network-id> [--disable-snat] The default behavior of a Neutron router is to source NAT all outbound traffic from instances that do not have a corresponding floating IP. To disable this functionality, append --disable-snat to the router-gateway-set command. Listing interfaces attached to routers To list the interfaces attached to routers, use the router-port-list command as follows: Syntax: router-port-list <router-id> The returned output includes the Neutron port ID, MAC address, IP address, and associated subnet of attached interfaces. Deleting internal interfaces To delete an internal interface from a router, use the router-interface-delete command as follows: Syntax: router-interface-delete <router-id> <INTERFACE> Here, INTERFACE is the ID of the subnet to be removed from the router. Deleting an interface from a router results in the associated Neutron port being removed from the database. Clearing the gateway interface Gateway interfaces cannot be removed from a router using the router-interface-delete command. Instead, the router-gateway-clear command must be used. To clear the gateway of a router, use the router-gateway-clear command as follows: Syntax: router-gateway-clear <router-id> Neutron includes checks that will prohibit the clearing of a gateway interface in the event that floating IPs or other resources from the network are associated with the router. Listing routers in the CLI To display a list of existing routers, use the Neutron router-list command as follows: Syntax: router-list [--tenant-id TENANT_ID] The returned output includes the router ID, name, external gateway network, and the SNAT state. Users will only see routers that exist in their tenant or project. When executed by an administrator, Neutron will return a listing of all routers across all tenants unless, the tenant ID is specified. Displaying router attributes in the CLI To display the attributes of a router, use the Neutron router-show command as follows: Syntax: router-show <router id> Among the output returned is the admin state, the external network, the SNAT state, and the tenant ID associated with the router. Updating router attributes in the CLI To update the attributes of a router, use the Neutron router-update command as follows: Syntax: router-update <router id> [--admin-state-up] [--routes destination=<network/cidr>,nexthop=<gateway_ip>] The admin-state-up attribute is a Boolean, which when set to false, does not allow Neutron to update interfaces within the router. This includes not adding floating IPs or additional internal interfaces to the router. Setting the value to true will allow queued changes to be applied. The routes option allows you to add static routes to the routing table of a Neutron router. To add static routes, use the following syntax: Syntax: neutron router-update <router id> --routes type=dict list=true destination=<network/cidr>,nexthop=<gateway_ip> Adding static routes to a router is an undocumented and broken feature in Havana. In Havana, the command results in the route being added to the database and router show output, while not being added to the routing table. To resolve this, add the following line to the [DEFAULT] block of the /etc/neutron/l3_agent.ini configuration file: root_helper = sudo neutron-rootwrap /etc/neutron/rootwrap.conf Restart the neutron-l3-agent service for changes to take effect. Deleting routers in the CLI To delete a router, use the Neutron router-delete command as follows: Syntax: router-delete <router id> Before a router can be deleted, all floating IPs and internal interfaces associated with the router must be unassociated or deleted. This may require deleting instances or detaching connected interfaces from instances. Network Address Translation Network Address Translation (NAT) is a networking concept that was developed in the early 1990s in response to the rapid depletion of IP addresses throughout the world. Prior to NAT, every host connected to the Internet had a unique IP address. OpenStack routers support two types of NAT: one-to-one many-to-one A one-to-one NAT is a method in which one IP address is directly mapped to another. Commonly referred to as a static NAT, a one-to-one NAT is often used to map a unique public address to a privately addressed host. Floating IPs utilize one-to-one NAT concepts. A many-to-one NAT is a method in which multiple addresses are mapped to a single address. A many-to-one NAT employs the use of port address translation (PAT). Neutron uses PAT to provide external access to instances behind the router when floating IPs are not assigned. For more information on network address translation, please visit Wikipedia at http://en.wikipedia.org/wiki/Network_address_translation. Floating IP addresses Tenant networks, when attached to a Neutron router, are meant to utilize the router as their default gateway. By default, when a router receives traffic from an instance and routes it upstream, the router performs a port address translation and modifies the source address of the packet to appear as its own external interface address. This ensures that the packet can be routed upstream and returned to the router, where it will modify the destination address to be that of the instance that initiated the connection. Neutron refers to this type of behavior as Source NAT. When users require direct inbound access to instances, a floating IP address can be utilized. A floating IP address in OpenStack is a static NAT that maps an external address to an internal address. This method of NAT allows instances to be reachable from external networks, such as the Internet. Floating IP addresses are configured on the external interface of the router that serves as the gateway for the instance, which is then responsible for modifying the source and/or destination address of packets depending on their direction. In this article, we learned that Neutron routers being a core component of networking in OpenStack, provides tenants the flexibility to design the network to best suit their application. Resources for Article: Further resources on this subject: Using OpenStack Swift [article] The OpenFlow Controllers [article] Troubleshooting [article]
Read more
  • 0
  • 0
  • 11682

article-image-rendering-web-pages-pdf-using-railo-open-source
Packt
01 Apr 2010
6 min read
Save for later

Rendering web pages to PDF using Railo Open Source

Packt
01 Apr 2010
6 min read
As a pre-requisite for this tutorial, you should be familiar with html, css and web technologies in general. You do not need to know any CFML (ColdFusion Markup Language). You should have an understanding of databases, particularly MySQL, which we will use in this example. Server environment For this tutorial, we are using a virtual machine (using VirtualBox) running Windows 2003 Server Standard, IIS, MySQL 5.1, and Railo 3.1. The code we will be writing is not platform specific. You can just as easily implement this on Linux or Mac OSX Server with MySQL and Apache. Website architecture Lets assume that we have the HTML layout code provided to us for our website, and that we need to make it “work” on the web server, pulling its page content from a MySQL database. In addition, we will add the capability for any page to render itself as a PDF for printing purposes. You will want to make sure you have done a few things first: Make sure Railo and MySQL are running on your server (or VM) Make sure you created a MySQL database, and a user that has permission to use your database For development (as opposed to production web servers), try running Railo Express, which runs in a terminal window. This allows you to see the templates it is running, and the full stack trace of errors when they occur. Setting up the Railo datasource The first thing we need to do is setup a Railo datasource. This named datasource will define our database credentials for our website. Open a web browser to the Railo Server Administrator, which is usually located at: http://your.server.com/railo-context/admin/server.cfm. Check the Railo documentation if you have trouble opening up the administrator. Enter your password to login. Once logged in, click on the Services / Datasource link in the left navigation. At the bottom of this page is where you can create a new datasource. Enter a datasource name (Letters and numbers only, no spaces, and start with a letter) and select MySQL as the database type. On the next screen, enter the MySQL server host name or ip address, and username and password for the user you created. All of the other settings can be kept with their default values. Scroll to the bottom and click on the “Create” button to complete the datasource configuration. Railo Administrator will test your connection, so you can confirm that it is setup properly. We created the datasource in the “server” context. When you deploy an application on a production server, you should create your datasources in the “web” context, so that it is only available to the website that needs it. Datasources created in the server context are accessible from any website on the same server. Setting up the website structure In the document root of your website (or in the directory you choose for this tutorial), you will need a couple of files. index.cfm – this is the default document, like index.html or default.htm header.cfm – this is the top portion of web pages, what appears above your page content. This is where you would put your html “design” code. footer.cfm – this is the bottom portion of your web pages, what shows up after your page content. This is where you would put your html “design” code. layout.css – the basic CSS layout for our pages styles.css – the CSS styles for your page content Let's look first at header.cfm: This file contains what you would expect to see at the top of a standard HTML web page, including head, title, meta tags, etc. There are a few different tags included in the content however. Any tags that begin with <cf…> are CFML language tags, that are processed by Railo and removed from the source code before the page is sent to your web browser. Just like PHP or ASP.net code, if somebody views the source of your web page, they won’t see your CFML code, but rather, they will see the html code, and any code that your CFML tags generate. <cfparam name="title" default="Untitled" /> This tag defines and sets a default value for a variable named “title.” This value can be overridden using a <cfset …> tag which we will see later. #title#</cfoutput> Any content inside <cfoutput>…</cfoutput> tags will be included in the output to your web browser. In this case, the title variable is written to the page output. As with all <cf..> tags, the <cfoutput> tags themselves will be removed from the web page output. Anything inside # characters will be evaluated as an expression. So if your code was <cfoutput>title</cfoutput>, then the literal word “title” would be included in your page output. When you put # characters around it, Railo will evaluate the expression and replace it with the result.</cfoutput></cf..> header.cfm also includes the two .css files we need for our layout and styles. These are standard css which should be familiar to you, and won’t be covered in this article. Let's next look at index.cfm <cfset title="Home Page"> This first tag sets a local variable called “title” and sets its value to “Home Page.” <cfinclude template="header.cfm"> This tag includes the file “header.cfm” into the current page, which means that any page output (the html, head, title, etc. tags) will be included in this page’s output. Notice that we set the local variable title in our page, and it gets used in the header.cfm file. Local variables are available to any pages that are included in the requested web page. The “Hello World” content is the main textual content of this web page, and can be any html or CFML generated content you want. After the main content, another <cfinclude…> tag includes footer.cfm, which includes the expected end of page tags such as </body> and </html> Take a look If you open your web browser and browse to index.cfm, you will see your basic web page layout, with a page title, and Hello World content. If you view the page source, you should see the combined content of the header.cfm, index.cfm and footer.cfm, with no <cf…> tags in the output, only pure HTML. You can easily organize and create static web pages like this, and like many other programming languages, structuring your website like this has many benefits. If you make a change to your header or footer, then all your pages inherit the change immediately. Likewise if you design a new layout or style for your site, applying it once to your header and footer then applies it to your entire website.
Read more
  • 0
  • 0
  • 11663

article-image-introduction-teamcity
Packt
21 Aug 2014
9 min read
Save for later

Introduction to TeamCity

Packt
21 Aug 2014
9 min read
In this article, by Manoj Mahalingam S, author of the book, Learning Continuous Integration with TeamCity, we will learn about Continuous Integration (CI) and its basic practices. The idea is to be on the same page when we talk about CI in the rest of the book and implement various solutions using TeamCity as a CI server. This article will also provide a high-level introduction to TeamCity, its features, and how effective it is when compared to competitive products such as Jenkins and ThoughtWorks' Go. (For more resources related to this topic, see here.) Introduction to Continuous Integration Continuous Integration is the name given to processes and practices that are involved in regularly integrating the work of several developers into a shared mainline/repository. My colleague Martin Fowler has written a popular article (http://martinfowler.com/articles/continuousIntegration.html) in which he defines CI as follows: "A software development practice where members of a team integrate their work frequently, usually each person integrates at least daily, leading to multiple integrations per day. Each integration is verified by an automated build (including test) to detect integration errors as quickly as possible. Many teams find that this approach leads to significantly reduced integration problems and allows a team to develop cohesive software more rapidly." Practices There are some key practices that must be followed to have an effective CI: Developers check in code to a common version-control repository. This happens regularly, at least once a day. Everything—source code, tests, database migrations scripts, build and release scripts, and so on—that is needed to get the application running is checked in to this common repository. Automated builds run off the checked-in code. This is where CI servers such as TeamCity come into the picture. CI servers run automated builds whenever there are changes in the version-control repository. Every commit has to go through this process of automated builds. The builds include the process of testing the checked-in code. This includes running unit tests, code coverage, functional tests, and code inspection among others. All the tests must be cleared for the build to be certified as a fully integrated build. The automated builds should result in well-tested artifacts/binaries/executables, depending on the type of the project. The artifacts must be easily available for anyone to download, and generally it is the CI server that provides the artifacts. In many setups, an external artifact repository such as Nexus or NuGet is utilized as well. The automated build process should be as quick as possible. The compilation, testing, and all the other steps to get the artifacts must be short to provide quick feedback. The automated process involved in getting the application running on a developer's box must be the same as the one used to run the CI. CI is about visibility. It must be clear what is happening to the builds and at what stage a particular commit is. Broken builds should be clearly highlighted and quickly acted upon. The CI server serves as a dashboard to this kind of activity. In TeamCity, users can quickly see the broken builds; the status of running builds and test failures, if any; communicate to the rest of the team that they are working on fixing a build; and pause the builds when needed. CI is also about team discipline. The team should ensure that broken builds are fixed as soon as possible and they never check in to a broken build. Developers must make sure that they run the build locally before checking in. Many of these can be attacked by technical solutions. For example, many VCSes allow the setting up of pre-commit hooks, which can be used to see whether the build is broken, and if so, prevent check ins. However, primarily, these are people's issues and have to be fixed appropriately. Automated deployments to a test environment against which we can run our automated functional tests is a key requirement in CI. The idea is to reuse the artifacts generated previously and deploy it into the environment without having to rebuild them again. The artifacts have to be agnostic of the environment they will be deployed into. Benefits CI brings a lot of value and benefits to the teams practicing it. Some of these include the following: Integrating code continuously leads to a more predictable and less tense integration process. Issues and bugs are identified and fixed earlier in the process. The presence of automated tests means that more bugs are caught as soon as a developer checks in the code. Also, it is inevitable that bugs escape the testing net. In such cases, the automated testing process that has been put in place encourages us to add tests so that similar bugs don't escape as well. One of the main benefits of CI is that you get reliable artifacts available to deploy at any point in time. The artifact has gone through lots of quality checks and can be deployed with more trust and less risk. This means that software can be delivered to the client/users frequently. CI encourages automation and helps in removing manual processes. As you build the foundation for automated tests and automated deployments as part of your CI, you are enabled to work further on this foundation and improve upon it over time. Continuous deployment and Continuous Delivery Continuous Delivery (CD) is the name given to the processes and practices through which applications are made available to be deployed into production at any time. CD is the natural extension to CI, which is more a developer team activity. CD is about making the built application ready to be deployed into production at any time. CD brings in the development team, the operations (ops) team, and the business together to ensure the application is released to production in a timely and appropriate way. Continuous deployment is different from Continuous Delivery. The former is about deploying every build into production, while the latter is about making every build available to be deployed into production. The actual deployment depends on various business and ops factors, and hence not every build might end up being deployed into production. When we refer to CD in this book, we are talking about Continuous Delivery. CI can be seen as a subset of CD. The point where CI ends and where the parts that were introduced from the following CD begin is not clearly defined, and they can vary from one setup to another. It can be generally defined that CI ends with getting out the artifacts needed to deploy the application, and CD adds in the ability to deploy them into production in a reliable manner. A key part of CD is what's called the build pipeline, which is what we will discuss in the next section. The build pipeline The idea of a build pipeline is to have your build process separated into various stages so that multiple builds can run at the same time. Each build can be in a different stage of the pipeline, thereby leading to a better throughput of builds. A build pipeline helps to get fast feedback for the team. The first stage of the pipeline generally does the compilation to produce the binaries and runs the unit tests. The artifacts from this stage are passed on to the later stages. The first stage is expected to be very fast in order to provide quick feedback to the team. The later stages perform various kinds of testing such as acceptance/functional testing and performance testing. These stages are generally slower due to their nature (for example, functional tests that hit the UI of the application are expected to be slower than the unit tests) and may be sequential or parallel depending on the requirements and/or resources available. The later stages also involve deployments to various environments such as the testing environment, against which we run the aforementioned tests, and User Acceptance Testing (UAT) environments that might be used for manual testing. The pipeline will culminate in the deployment of the artifacts to production-like environments such as staging and eventually production itself. Not every stage of a build pipeline is automatically triggered. Deployments to most of the environments outside the environments used for automated testing are probably done manually as and when required. The following diagram shows a high-level view of a build pipeline for a project: The build stage does the compilation, runs the unit tests, and produces the binaries. The binaries are then deployed into a testing environment for CI purposes. Quick smoke tests are then run to verify that the build is stable. Then, longer acceptance/functional tests are run. All the stages so far were automatic. The pipeline branches into a set of stages performing deployments to various environments such as UAT, staging, and production on one side, and, on the other side, a couple of stages performing performance tests after the pipeline is deployed into a performance environment. Deployment to various environments such as UAT is generally manual and is done as needed. The exact implementation of a build pipeline will vary from project to project and team to team. Typically, there are other dependencies such as libraries that come into the picture, but the overall structure should be similar to this. The build pipeline, apart from aiding in fast builds and quick feedback, also enables you to ensure that only the builds that have gone through the rigorous testing process are finally deployed into production. The build pipeline is also called the deployment pipeline. Introduction to TeamCity TeamCity is a CI server from JetBrains and comes with a lot of features out of the box to get you started quickly with CI for your projects. As a CI server, TeamCity can detect changes in version-control repositories and trigger builds whenever new code is checked in. TeamCity can be configured to perform the build activities, which includes the compilation of source code, running unit tests and integration tests, deploying the built executables into a testing environment to perform functional tests, and exposing artifacts for downloads. TeamCity is designed to help you follow the best practices of CI. With its ability to download artifacts from another build configuration, for example, TeamCity enables you to follow the approach of build once and deploy everywhere. TeamCity is feature-rich and flexible enough to allow you to follow the practices that suit your team and your needs the best. This book will be using TeamCity 8.0.x, but we will also be looking at some of the newer features of the 8.1.x release.
Read more
  • 0
  • 0
  • 11651

article-image-generate-prime-numbers-ancient-greek-connection
Richard Gall
16 Mar 2018
2 min read
Save for later

Prime numbers, modern encryption and their ancient Greek connection!

Richard Gall
16 Mar 2018
2 min read
Prime numbers are incredibly important in a number of fields, from computer science to cybersecurity. But they are incredibly mysterious - they are quite literally enigmas. They have been the subject of thousands of years of research and exploration but they have still not been cracked - we are yet to find a formula that will help generate prime numbers easily. Prime numbers are particularly integral to modern encryption - when a file is encrypted, the number used to do so is built using two primes. The only way to decrypt it is to work out the prime factors of that gargantuan number, a task which is almost impossible even with the most extensive computing power currently at our disposal. As well as this, prime numbers are also used as error correcting codes and in mass storage and data transmission. Did you know the Greeks were one of the early champions for our modern encryption systems? Find out how to generate prime numbers manually using a method devised by the Greek mathematician, Eratothenes, in this fun video from the video course by Packt, Fundamental Algorithms in Scala. [embed]https://www.youtube.com/watch?v=cd8v-Jo8obs&t=56s[/embed]  
Read more
  • 0
  • 0
  • 11644
Unlock access to the largest independent learning library in Tech for FREE!
Get unlimited access to 7500+ expert-authored eBooks and video courses covering every tech area you can think of.
Renews at €18.99/month. Cancel anytime
article-image-article-key-features-explained
Packt
26 Dec 2012
21 min read
Save for later

Key Features Explained

Packt
26 Dec 2012
21 min read
Service Bus The Windows Azure Service Bus provides a hosted, secure, and widely available infrastructure for widespread communication, large-scale event distribution, naming, and service publishing. Service Bus provides connectivity options for Windows Communication Foundation (WCF) and other service endpoints, including REST endpoints, that would otherwise be difficult or impossible to reach. Endpoints can be located behind Network Address Translation (NAT) boundaries, or bound to frequently changing, dynamically assigned IP addresses, or both. Getting started To get started and use the features of Services Bus, you need to make sure you have the Windows Azure SDK installed. Queues Queues in the AppFabric feature (different from Table Storage queues) offer a FIFO message delivery capability. This can be an outcome for those applications that expect messages in a certain order. Just like with ordinary Azure Queues, Service Bus Queues enable the decoupling of your application components and can still function, even if some parts of the application are offline. Some differences between the two types of queues are (for example) that the Service Bus Queues can hold larger messages and can be used in conjunction with Access Control Service. Working with queues To create a queue, go to the Windows Azure portal and select the Service Bus, Access Control & Caching tab. Next, select Service Bus, select the namespace, and click on New Queue. The following screen will appear. If you did not set up a namespace earlier you need to create a namespace before you can create a queue: There are some properties that can be configured during the setup process of a queue. Obviously, the name uniquely identifies the queue in the namespace. Default Message Time To Live configures messages having this default TTL. This can also be set in code and is a TimeSpan value. Duplicate Detection History Time Window implicates how long the message ID (unique) of the received messages will be retained to check for duplicate messages. This property will be ignored if the Required Duplicate Detection option is not set. Keep in mind that a long detection history results in the persistency of message IDs during that period. If you process many messages, the queue size will grow and so does your bill. When a message expires or when the limit of the queue size is reached, it will be deadlettered. This means that they will end up in a different queue named $DeadLetterQueue. Imagine a scenario where a lot of traffic in your queue results in messages in the dead letter queue. Your application should be robust and process these messages as well. The lock duration property defines the duration of the lock when the PeekLock() method is called. The PeekLock() method hides a specific message from other consumers/processors until the lock duration expires. Typically, this value needs to be sufficient to process and delete the message. A sample scenario Remember the differences between the two queue types that Windows Azure offers, where the Service Bus queues are able to guarantee first-in first-out and to support transactions. The scenario is when a user posts a geotopic on the canvas containing text and also uploads a video by using the parallel upload functionality. What should happen next is for the WCF service CreateGeotopic() to post a message in the queue to enter the geotopic, but when the file finishes uploading, there is also a message sent to the queue. These two together should be in a single transaction. Geotopia.Processor processes this message but only if the media file is finished uploading. In this example, you can see how a transaction is handled and how a message can be abandoned and made available on the queue again. If the geotopic is validated as a whole (file is uploaded properly), the worker role will reroute the message to a designated audit trail queue to keep track of actions made by the system and also send to a topic (see next section) dedicated to keeping messages that need to be pushed to possible mobile devices. The messages in this topic will again be processed by a worker role. The reason for choosing a separate worker role is that it creates a role, a loosely-coupled solution, and possible to be fine-grained by only scaling the back-end worker role. See the following diagram for an overview of this scenario: In the previous section, we already created a queue named geotopicaqueue. In order to work with queues, you need the service identity (in this case we use a service identity with a symmetric issuer and the key credentials) of the service namespace. Preparing the project In order to make use of the Service Bus capabilities, you need to add a reference to Microsoft.ServiceBus.dll, located in <drive>:Program FilesMicrosoft SDKsWindows Azure.NET SDK2012-06ref. Next, add the following using statements to your file: using Microsoft.ServiceBus; using Microsoft.ServiceBus.Messaging; Your project is now ready to make use of Service Bus queues. "Endpoint=sb://<servicenamespace>.servicebus.windows. net/;SharedSecretIssuer=<issuerName>;SharedSecretValue=<yoursecret>" The properties of the queue you configured in the Windows Azure portal can also be set programmatically. Sending messages Messages that are sent to a Service Bus queue are instances of BrokeredMessage. This class contains standard properties such as TimeToLive and MessageId. An important property is Properties, which is of type IDictionary<string, object>, where you can add additional data. The body of the message can be set in the constructor of BrokerMessage, where the parameter must be of a type decorated with the [Serializable] attribute. The following code snippet shows how to send a message of type BrokerMessage: MessagingFactory factory = MessagingFactory.CreateFromConnectionString (connectionString); MessageSender sender = factory.CreateMessageSender("geotopiaqueue"); sender.Send(new BrokeredMessage( new Geotopic { id = id, subject = subject, text = text, PostToFacebook = PostToFacebook, accessToken = accessToken, MediaFile = MediaFile //Uri of uploaded mediafile })); As the scenario depicts a situation where two messages are expected to be sent in a certain order and to be treated as a single transaction, we need to add some more logic to the code snippet. Right before this message is sent, the media file is uploaded by using the BlobUtil class. Consider sending the media file together with BrokeredMessage if it is small enough. This might be a long-running operation, depending on the size of the file. The asynchronous upload process returns Uri, which is passed to BrokeredMessage. The situation is: A multimedia file is uploaded from the client to Windows Azure Blob storage using a parallel upload (or passed on in the message). A Parallel upload is breaking up the media file in several chunks and uploading them separately by using multithreading. A message is sent to geotopiaqueue, and Geotopia.Processor processes the messages in the queues in a single transaction. Receiving messages On the other side of the Service Bus queue resides our worker role, Geotopia.Processor, which performs the following tasks: It grabs the messages from the queue Sends the message straight to a table in Windows Azure Storage for auditing purposes Creates a geotopic that can be subscribed to (see next section) The following code snippet shows how to perform these three tasks: MessagingFactory factory = MessagingFactory.CreateFromConnectionString (connectionString); MessageReceiver receiver = factory.CreateMessageReceiver("geotopiaqueue "); BrokeredMessage receivedMessage = receiver.Receive(); try { ProcessMessage(receivedMessage); receivedMessage.Complete(); } catch (Exception e) { receivedMessage.Abandon(); } Cross-domain communication We created a new web role in our Geotopia solution, hosting the WCF services we want to expose. As the client is a Silverlight one (and runs in the browser), we face cross-domain communication. To protect against security vulnerabilities and to prevent cross-site requests from a Silverlight client to some services (without the notice of the user), Silverlight by default allows only site-of-origin communication. A possible exploitation of a web application is cross-site forgery, exploits that can occur when cross-domain communication is allowed; for example, a Silverlight application sending commands to some service running on the Internet somewhere. As we want the Geotopia Silverlight client to access the WCF service running in another domain, we need to explicitly allow cross-domain operations. This can be achieved by adding a file named clientaccesspolicy.xml at the root of the domain where the WCF service is hosted and allowing this cross-domain access. Another option is to add a crossdomain.xml file at the root where the service is hosted. Please go to http://msdn.microsoft.com/en-us/library/cc197955(v=vs.95).aspx to find more details on the cross-domain communication issues. Comparison The following table shows the similarities and differences between Windows Azure and Service Bus queues: Criteria Windows Azure queue Service Bus queue Ordering guarantee No, but based on besteffort first-in, first out First-in, first-out Delivery guarantee At least once At most once; use the PeekLock() method to ensure that no messages are missed. PeekLock() together with the Complete() method enable a two-stage receive operation. Transaction support No Yes, by using TransactionScope Receive Mode Peek & Lease Peek & Lock Receive & Delete Lease/Lock duration Between 30 seconds and 7 days Between 60 seconds and 5 minutes Lease/Lock granularity Message level Queue level Batched Receive Yes, by using GetMessages(count) Yes, by using the prefetch property or the use of transactions Scheduled Delivery Yes Yes Automatic dead lettering No Yes In-place update Yes No Duplicate detection No Yes WCF integration No Yes, through WCF bindings WF integration Not standard; needs a customized activity Yes, out-of-the-box activities Message Size Maximum 64 KB Maximum 256 KB Maximum queue size 100 TB, the limits of a storage account 1, 2, 3, 4, or 5 GB; configurable Message TTL Maximum 7 days Unlimited Number of queues Unlimited 10,000 per service namespace Mgmt protocol REST over HTTP(S) REST over HTTPS Runtime protocol REST over HTTP(S) REST over HTTPS TCP with TLS Queue naming rules Maximum of 63 characters Maximum of 260 characters Queue length function Yes, value is approximate Yes, exact value Throughput Maximum of 2,000 messages/second Maximum of 2,000 messages/second Authentication Symmetric key ACS claims Role-based access control No Yes through ACS roles Identity provider federation No Yes Costs $0.01 per 10,000 transactions $ 0.01 per 10,000 transactions Billable operations Every call that touches "storage"' Only Send and Receive operations Storage costs $0.14 per GB per month None ACS transaction costs None, since ACS is not supported $1.99 per 100,000 token requests Background information There are some additional characteristics of Service Bus queues that need your attention: In order to guarantee the FIFO mechanism, you need to use messaging sessions. Using Receive & Delete in Service Bus queues reduces transaction costs, since it is counted as one. The maximum size of a Base64-encoded message on the Window Azure queue is 48 KB and for standard encoding it is 64 KB. Sending messages to a Service Bus queue that has reached its limit will throw an exception that needs to be caught. When the throughput has reached its limit, the HTTP 503 error response is returned from the Windows Azure queue service. Implement retrying logic to tackle this issue. Throttled requests (thus being rejected) are not billable. ACS transactions are based on instances of the message factory class. The received token will expire after 20 minutes, meaning that you will only need three tokens per hour of execution. Topics and subscriptions Topics and subscriptions can be useful in a scenario where (instead of a single consumer, in the case of queues) multiple consumers are part of the pattern. Imagine in our scenario where users want to be subscribed to topics posted by friends. In such a scenario, a subscription is created on a topic and the worker role processes it; for example, mobile clients can be push notified by the worker role. Sending messages to a topic works in a similar way as sending messages to a Service Bus queue. Preparing the project In the Windows Azure portal, go to the Service Bus, Access Control & Caching tab. Select Topics and create a new topic, as shown in the following screenshot: Next, click on OK and a new topic is created for you. The next thing you need to do is to create a subscription on this topic. To do this, select New Subscription and create a new subscription, as shown in the following screenshot: Using filters Topics and subscriptions, by default, it is a push/subscribe mechanism where messages are made available to registered subscriptions. To actively influence the subscription (and subscribe only to those messages that are of your interest), you can create subscription filters. SqlFilter can be passed as a parameter to the CreateSubscription method of the NamespaceManager class. SqlFilter operates on the properties of the messages so we need to extend the method. In our scenario, we are only interested in messages that are concerning a certain subject. The way to achieve this is shown in the following code snippet: BrokeredMessage message = new BrokeredMessage(new Geotopic { id = id, subject = subject, text = text, PostToFacebook = PostToFacebook, accessToken = accessToken, mediaFile = fileContent }); //used for topics & subscriptions message.Properties["subject"] = subject; The preceding piece of code extends BrokeredMessage with a subject property that can be used in SqlFilter. A filter can only be applied in code on the subscription and not in the Windows Azure portal. This is fine, because in Geotopia, users must be able to subscribe to interesting topics, and for every topic that does not exist yet, a new subscription is made and processed by the worker role, the processor. The worker role contains the following code snippet in one of its threads: Uri uri = ServiceBusEnvironment.CreateServiceUri ("sb", "<yournamespace>", string.Empty); string name = "owner"; string key = "<yourkey>"; //get some credentials TokenProvider tokenProvider = TokenProvider.CreateSharedSecretTokenProvider(name, key); // Create namespace client NamespaceManager namespaceClient = new NamespaceManager(ServiceBusEnvironment.CreateServiceUri ("sb", "geotopiaservicebus", string.Empty), tokenProvider); MessagingFactory factory = MessagingFactory.Create(uri, tokenProvider); BrokeredMessage message = new BrokeredMessage(); message.Properties["subject"] = "interestingsubject"; MessageSender sender = factory.CreateMessageSender("dataqueue"); sender.Send(message); //message is send to topic SubscriptionDescription subDesc = namespaceClient.CreateSubscription("geotopiatopic", "SubscriptionOnMe", new SqlFilter("subject='interestingsubject'")); //the processing loop while(true) { MessageReceiver receiver = factory.CreateMessageReceiver ("geotopiatopic/subscriptions/SubscriptionOnMe"); //it now only gets messages containing the property 'subject' //with the value 'interestingsubject' BrokeredMessage receivedMessage = receiver.Receive(); try { ProcessMessage(receivedMessage); receivedMessage.Complete(); } catch (Exception e) { receivedMessage.Abandon(); } } Windows Azure Caching Windows Azure offers caching capabilities out of the box. Caching is fast, because it is built as an in-memory (fast), distributed (running on different servers) technology. Windows Azure Caching offers two types of cache: Caching deployed on a role Shared caching When you decide to host caching on your Windows Azure roles, you need to pick from two deployment alternatives. The first is dedicated caching, where a worker role is fully dedicated to run as a caching store and its memory is used for caching. The second option is to create a co-located topology, meaning that a certain percentage of available memory in your roles is assigned and reserved to be used for in-memory caching purposes. Keep in mind that the second option is the most costeffective one, as you don't have a role running just for its memory. Shared caching is the central caching repository managed by the platform which is accessible for your hosted services. You need to register the shared caching mechanism on the portal in the Service Bus, Access Control & Caching section of the portal. You need to configure a namespace and the size of the cache (remember, there is money involved). This caching facility is a shared one and runs inside a multitenant environment. Caching capabilities Both the shared and dedicated caching offer a rich feature set. The following table depicts this: Feature Explanation ASP.NET 4.0 caching providers Programming model When you build ASP.NET 4.0 applications and deploy them on Windows Azure, the platform will install caching providers for them. This enables your ASP.NET 4.0  applications to use caching easily.   You can use the Microsoft.ApplicationServer.Caching namespace to perform CRUD operations on your cache. The application using the cache is responsible for populating and reloading the cache, as the programming model is based on the cache-aside pattern. This means that initially the cache is empty and will be populated during the lifetime of the application. The application checks whether the desired data is present. If not, the  application reads it from (for example) a database and inserts it into the cache.   The caching mechanism deployed on one of your roles, whether dedicated or not, lives up to the high availability of Windows Azure. It saves copies of your items in cache, in case a role instance goes down. Configuration model Configuration of caching (server side) is not relevant in the case of shared caching, as this is the standard, out-of-the-box functionality that can only vary in size, namespace, and location.   It is possible to create named caches. Every single cache has its own configuration settings, so you can really fine-tune your caching requirements. All settings are stored in the service definition and service configuration files. As the settings of named caches are stored in JSON format, they are difficult to read.   If one of your roles wants to access Windows Azure Cache, it needs some configuration as well. A DataCacheFactory object is used to return the DataCache objects that represent the named caches. Client cache settings are stored in the designated app.config or web.config files.   A configuration sample is shown later on in this section, together with some code snippets. Security model The two types of caching (shared and role-based) have two different ways of handling security.   Role-based caching is secured by its endpoints, and only those which are allowed to use these endpoints are permitted to touch the cache. Shared caching is secured by the use of an authentication token. Concurrency model As multiple clients can access and modify cache items simultaneously, there are concurrency issues to take care of; both optimistic and pessimistic concurrency models are available.   In the optimistic concurrency model, updating any objects in the cache does not result in locks. Updating an item in the cache will only take place if Azure detects that the updated version is the same as the one that currently resides in the cache.   When you decide to use the pessimistic concurrency model, items are locked explicitly by the cache client. When an item is locked, other lock requests are rejected by the platform. Locks need to be released by the client or after some configurable time-out, in order to prevent eternal locking. Regions and tagging Cached items can be grouped together in a so-called region. Together with additional tagging of cached items, it is possible to search for tagged items within a certain region. Creating a region results in adding cache items to be stored on a single server (analogous to partitioning). If additional backup copies are enabled, the region with all its items is also saved on a different server, to maintain availability. Notifications It is possible to have your application notified by Windows Azure when cache operations occur. Cache notifications exist for both operations on regions and items. A notification is sent when CreateRegion, ClearRegion, or RemoveRegion is executed. The operations AddItem, ReplaceItem, and RemoveItem on cached items also cause notifications to be sent.   Notifications can be scoped on the cache, region, and item level. This means you can configure them to narrow the scope of notifications and only receive those that are relevant to your applications.   Notifications are polled by your application at a configurable interval. Availability To keep up the high availability you are used to on Windows Azure, configure your caching role(s) to maintain backup copies. This means that the platform replicates copies of your cache within your deployment across different fault domains. Local caching To minimize the number of roundtrips between cache clients and the Windows Azure cache, enable local caching. Local caching means that every cache clients maintains a reference to the item in-memory itself. Requesting that same item again will cause an object returned from the local cache instead of the role-based cache. Make sure you choose the right lifetime for your objects, otherwise you might work with outdated cached items. Expiration and Eviction Cache items can be removed explicitly or implicitly by expiration or eviction.   The process of expiration means that the caching facility removes items from the cache automatically. Items will be removed after their time-out value expires, but keep in mind that locked items will not be removed even if they pass their expiration date. Upon calling the Unlock method, it is possible to extend the expiration date of the cached item.   To ensure that there is sufficient memory available for caching purposes, the least recently used (LRU) eviction is supported. The process of eviction means that memory will be cleared and cached items will be evicted when certain memory thresholds are exceeded.   By default, Shared Cache items expire after 48 hours. This behavior can be overridden by the overloads of the Add and Put methods. Setting it up To enable role-based caching, you need to configure it in Visual Studio. Open the Caching tab of the properties of your web or worker role (you decide which role is the caching one). Fill out the settings, as shown in the following screenshot: The configuration settings in this example cause the following to happen: Role-based caching is enabled. The specific role will be a dedicated role just for caching. Besides the default cache, there are two additional, named caches for different purposes. The first is a high-available cache for recently added geotopics with a sliding window. This means that every time an item is accessed, its expiration time is reset to the configured 10 minutes. For our geotopics, this is a good approach, since access to recently posted geotopics is heavy at first but will slow down as time passes by (and thus they will be removed from the cache eventually). The second named cache is specifically for profile pictures with a long time-to-live, as these pictures will not change too often. Caching examples In this section, several code snippets explain the use of Window Azure caching and clarify different features. Ensure that you get the right assemblies for Windows Azure Caching by running the following command in the Package Manager Console: Install-Package Microsoft.WindowsAzure.Caching. Running this command updates the designated config file for your project. Replace the [cache cluster role name] tag in the configuration file with the name of the role that hosts the cache. Adding items to the cache The following code snippet demonstrates how to access a named cache and how to add and retrieve items from it (you will see the use of tags and the sliding window): DataCacheFactory cacheFactory = new DataCacheFactory(); DataCache geotopicsCache = cacheFactory.GetCache("RecentGeotopics"); //get reference to this named cache geotopicsCache.Clear(); //clear the whole cache DataCacheTag[] tags = new DataCacheTag[] { new DataCacheTag("subject"), new DataCacheTag("test")}; //add a short time to live item DataCacheItemVersion version = geotopicsCache.Add(geotopicID, new Geotopic(), TimeSpan.FromMinutes(1)/* overrides default 10 minutes */, tags); //add a default item geotopicsCache.Add("defaultTTL", new Geotopic()); //default 10 minutes //let time pass for some minutes DataCacheItem item = geotopicsCache.GetCacheItem(geotopicID); // returns null! DataCacheItem defaultItem = geotopicsCache.GetCacheItem("defaultTTL"); //sliding window shows up //versioning, optimistic locking geotopicsCache.Put("defaultTTL", new Geotopic(), defaultItem.Version); //will fail if versions are not equal! Session state and output caching Two interesting areas in which Windows Azure caching can be applied are caching the session state of ASP.NET applications and the caching of HTTP responses, for example, complete pages. In order to use Windows Azure caching (that is, the role-based version), to maintain the session state, you need to add the following code snippet to the web.config file for your web application: <sessionState mode="Custom" customProvider="AppFabricCacheSessionStor eProvider"> <providers> <add name="AppFabricCacheSessionStoreProvider" type="Microsoft.Web.DistributedCache. DistributedCacheSessionStateStoreProvider, Microsoft.Web. DistributedCache" cacheName="default" useBlobMode="true" dataCacheClientName="default" /> </providers> </sessionState> The preceding XML snippet causes your web application to use the default cache that you configured on one of your roles. To enable output caching, add the following section to your web.config file: <caching> <outputCache defaultProvider="DistributedCache"> <providers> <add name="DistributedCache" type="Microsoft.Web.DistributedCache. DistributedCacheOutputCacheProvider, Microsoft.Web.DistributedCache" cacheName="default" dataCacheClientName="default" /> </providers> </outputCache> </caching> This will enable output caching for your web application, and the default cache will be used for this. Specify a cache name, if you have set up a specific cache for output caching purposes. The pages to be cached determine how long they will remain in the cache and set the different version of the page, depending on the parameter combinations. <%@ OutputCache Duration="60" VaryByParam="*" %>
Read more
  • 0
  • 0
  • 11641

article-image-the-future-of-net-neutrality-is-being-decided-in-court-right-now-as-mozilla-takes-on-the-fcc
Richard Gall
01 Feb 2019
3 min read
Save for later

The future of net neutrality is being decided in court right now, as Mozilla takes on the FCC

Richard Gall
01 Feb 2019
3 min read
Back in August, in a bid to defend net neutrality, Mozilla filed a case against the FCC, opposing the FCC's rollback of the laws that defend users against the interests of ISPs. Today, the oral arguments in that case have come to court in Washington D.C., making it an important day in the fight to save the very principle of net neutrality. What is net neutrality and why did the FCC roll it back? To understand the significance of today, it's important to know what net neutrality is, exactly, and how and why the FCC removed the rules that put it in place. Essentially, net neutrality is the principle that all internet service providers must treat all content and services equally. It means your internet provider can't slow your access to Netflix, or prevent you from accessing any other content for commercial reasons. Essentially net neutrality protects users like you and me, and prevents a market emerging where companies and individuals can pay more for faster speeds or more access to services. The argument against net neutrality is grounded in the liberal economic principle that understands regulation as necessarily restrictive. It suggests that regulation will actually lead to price rises, rather than pushing them down. From a political perspective too, the argument is that regulating the internet in this way effectively puts it under government control - that's misleading, but it's easy to see how that argument can be peddled. The two key arguments in the net neutrality case against the FCC The case will center upon two arguments. The first is whether the FCC's decision to repeal the legislation was warranted in the first place. As a Federal agency, the FCC is forbidden by the Administrative Procedure Act to make decisions that could be described as "arbitrary and capricious." In essence, this means they can't make decisions based on the opinions and personal judgements of those that lead the organization. All regulatory decisions need to be clear and considered, and, of course, backed up by compelling evidence. From the FCC's perspective, the decision to repeal net neutrality legislation was sound. The agency argued, for example, that the rules were damaging investment in infrastructure, and restricting private businesses to develop their products and services in a way that would ultimately benefit users. This position has, however, been disputed by a Wired report that found that investment was high from market leaders during the period when net neutrality legislation was in place. The second point that will be crucial is whether ISPs are simply an information service or telecommunications provider. This distinction is important - information services are less tightly regulated than telecommunications (think of all the various ways subscription services make money). Under net neutrality rules, ISPs are regarded as telecommunications companies - by removing net neutrality rules, the FCC is saying they are merely information services. At court already this morning, Pantelis Michalopoulos, one of the plaintiff attorneys against the FCC, compared the assertion that an ISP isn't a telecommunications company to Magritte's famous painting The Treachery of Images. "This is like a surrealist painting that shows a pipe and says ‘this is not a pipe,’” The EFF reports he said in court. https://twitter.com/EFFLive/status/1091351488540995584 How to follow the case Representatives from the Electronic Frontier Foundation are live tweeting from the courtroom from @EFFLive. If you want to follow the debates and arguments - as well as plenty of useful commentary and information from the EFF, make sure you follow them.
Read more
  • 0
  • 0
  • 11626

article-image-article-what_is_ngui
Packt
20 Jan 2014
8 min read
Save for later

What is NGUI?

Packt
20 Jan 2014
8 min read
(For more resources related to this topic, see here.) The Next-Gen User Interface kit is a plugin for Unity 3D. It has the great advantage of being easy to use, very powerful, and optimized compared to Unity's built-in GUI system, UnityGUI. Since it is written in C#, it is easily understandable and you may tweak it or add your own features, if necessary. The NGUI Standard License costs $95. With this, you will have useful example scenes included. I recommend this license to start comfortably—a free evaluation version is available, but it is limited, outdated, and not recommended. The NGUI Professional License, priced at $200, gives you access to NGUI's GIT repository to access the latest beta features and releases in advance. A $2000 Site License is available for an unlimited number of developers within the same studio. Let's have an overview of the main features of this plugin and see how they work. UnityGUI versus NGUI With Unity's GUI, you must create the entire UI in code by adding lines that display labels, textures, or any other UI element on the screen. These lines have to be written inside a special function, OnGUI(), that is called for every frame. This is no longer necessary; with NGUI, UI elements are simple GameObjects! You can create widgets—this is what NGUI calls labels, sprites, input fields, and so on—move them, rotate them, and change their dimensions using handles or the Inspector. Copying, pasting, creating prefabs, and every other useful feature of Unity's workflow is also available. These widgets are viewed by a camera and rendered on a layer that you can specify. Most of the parameters are accessible through Unity's Inspector, and you can see what your UI looks like directly in the Game window, without having to hit the Play button. Atlases Sprites and fonts are all contained in a large texture called atlas. With only a few clicks, you can easily create and edit your atlases. If you don't have any images to create your own UI assets, simple default atlases come with the plugin. That system means that for a complex UI window composed of different textures and fonts, the same material and texture will be used when rendering. This results in only one draw call for the entire window. This, along with other optimizations, makes NGUI the perfect tool to work on mobile platforms. Events NGUI also comes with an easy-to-use event framework that is written in C#. The plugin comes with a large number of additional components that you can attach to GameObjects. These components can perform advanced tasks depending on which events are triggered: hover, click, input, and so on. Therefore, you may enhance your UI experience while keeping it simple to configure. Code less, get more! Localization NGUI comes with its own localization system, enabling you to easily set up and change your UI's language with the push of a button. All your strings are located in the .txt files: one file per language. Shaders Lighting, normal mapping, and refraction shaders are supported in NGUI, which can give you beautiful results. Clipping is also a shader-controlled feature with NGUI, used for showing or hiding specific areas of your UI. We've now covered what NGUI's main features are, and how it can be useful to us as a plugin, and now it's time to import it inside Unity. Importing NGUI After buying the product from the Asset Store or getting the evaluation version, you have to download it. Perform the following steps to do so: Create a new Unity project. Navigate to Window | Asset Store. Select your downloads library. Click on the Download button next to NGUI: Next-Gen UI. When the download completes, click on the NGUI icon / product name in the library to access the product page. Click on the Import button and wait for a pop-up window to appear. Check the checkbox for NGUI v.3.0.2.unity package and click on Import. In the Project view, navigate to Assets | NGUI and double-click on NGUI v.3.0.2. A new imported pop-up window will appear. Click on Import again. Click any button on the toolbar to refresh it.The NGUI tray will appear! The NGUI tray will look like the following screenshot: You have now successfully imported NGUI to your project. Let's create your first 2D UI. Creating your UI We will now create our first 2D user interface with NGUI's UI Wizard. This wizard will add all the elements needed for NGUI to work. Before we continue, please save your scene as Menu.unity. UI Wizard Create your UI by opening the UI Wizard by navigating to NGUI | Open | UIWizard from the toolbar. Let's now take a look at the UI Wizard window and its parameters. Window You should now have the following pop-up window with two parameters: Parameters The two parameters are as follows: Layer: This is the layer on which your UI will be displayed Camera: This will decide if the UI will have a camera, and its drop-down options are as follows: None: No camera will be created Simple 2D:Uses a camera with orthographic projection Advanced 3D:Uses a camera with perspective projection Separate UI Layer I recommend that you separate your UI from other usual layers. We should do it as shown in the following steps: Click on the drop-down menu next to the Layer parameter. Select Add Layer. Create a new layer and name it GUI2D. Go back to the UI Wizard window and select this new GUI2D layer for your UI. You can now click on the Create Your UI button. Your first 2D UI has been created! Your UI structure The wizard has created four new GameObjects on the scene for us: UI Root (2D) Camera Anchor Panel Let's now review each in detail. UI Root (2D) The UIRoot component scales widgets down to keep them at a manageable size. It is also responsible for the Scaling Style—it will either scale UI elements to remain pixel perfect or to occupy the same percentage of the screen, depending on the parameters you specify. Select the UI Root (2D) GameObject in the Hierarchy. It has the UIRoot.cs script attached to it. This script adjusts the scale of the GameObject it's attached to in order to let you specify widget coordinates in pixels, instead of Unity units as shown in the following screenshot: Parameters The UIRoot component has four parameters: Scaling Style: The following are the available scaling styles: PixelPerfect:This will ensure that your UI will always try to remain at the same size in pixels, no matter what resolution. In this scaling mode, a 300 x 200 window will be huge on a 320 x 240 screen and tiny on a 1920 x 1080 screen. That also means that if you have a smaller resolution than your UI, it will be cropped. FixedSize:This will ensure that your UI will be proportionally resized depending on the screen's height. The result is that your UI will not be pixel perfect but will scale to fit the current screen size. FixedSizeOnMobiles:This will ensure fixed size on mobiles and pixel perfect everywhere else. Manual Height: With the FixedSize scaling style, the scale will be based on this height. If your screen's height goes over or under this value, it will be resized to be displayed identically while maintaining the aspect ratio(width/height proportional relationship). Minimum Height: With the PixelPerfect scaling style, this parameter defines the minimum height for the screen. If your screen height goes below this value, your UI will resize. It will be as if the Scaling Style parameter was set to FixedSize with Manual Height set to this value. Maximum Height: With the PixelPerfect scaling style, this parameter defines the maximum height for the screen. If your screen height goes over this value,your UI will resize. It will be as if the ScalingStyle parameter was set to FixedSize with Manual Height set to this value. Please set the Scaling Style parameter to FixedSize with a Manual Height value of 1080. This will allow us to have the same UI on any screen size up to 1920 x 1080. Even though the UI will look the same on different resolutions, the aspect ratio is still a problem since the rescale is based on the screen's height only. If you want to cover both 4:3 and 16:9 screens, your UI should not be too large—try to keep it square.Otherwise, your UI might be cropped on certain screen resolutions. On the other hand, if you want a 16:9 UI, I recommend you force this aspect ratio only. Let's do it now for this project by performing the following steps: Navigate to Edit| Project Settings | Player. In the Inspectoroption, unfold the Resolution and Presentationgroup. Unfold the Supported Aspect Ratios group. Check only the 16:9 box. Summary In this article, we discussed NGUI's basic workflow—it works with GameObjects, uses atlases to combine multiple textures in one large texture, has an event system, can use shaders, and has a localization system. After importing the NGUI plugin, we created our first 2D UI with the UI Wizard, reviewed its parameters, and created our own GUI 2D layer for our UI to reside on. Resources for Article: Further resources on this subject: Unity 3D Game Development: Don't Be a Clock Blocker [Article] Component-based approach of Unity [Article] Unity 3: Building a Rocket Launcher [Article]
Read more
  • 0
  • 0
  • 11613

article-image-storing-apache-storm-data-in-elasticsearch
Richa Tripathi
27 Dec 2017
6 min read
Save for later

Storing Apache Storm data in Elasticsearch

Richa Tripathi
27 Dec 2017
6 min read
[box type="note" align="" class="" width=""]This article is an excerpt from a book by Ankit Jain titled Mastering Apache Storm. This book explores various real-time processing functionalities offered by Apache Storm such as parallelism, data partitioning, and more.[/box] In this article, we are going to cover how to store the data processed by Apache Storm in Elasticsearch. Elasticsearch is an open source, distributed search engine platform developed on Lucene. It provides a multitenant-capable, full-text search engine capability.Though Apache storm is meant for real-time data processing, in most cases, we need to store the processed data in a data store so that it can be used for further batch analysis and to execute the batch analysis queries on the data stored. We assume that Elasticsearch is running on your environment. Please refer to https://www.elastic.co/guide/en/elasticsearch/reference/2.3/_installation.html to install Elasticsearch on any of the boxes if you don't have any running Elasticsearch cluster. Go through the following steps to integrate Storm with Elasticsearch: Create a Maven project using com.stormadvance for the groupID and storm_elasticsearch for the artifactID. Add the following dependencies and repositories to the pom.xml file: <dependencies> <dependency> <groupId>org.elasticsearch</groupId> <artifactId>elasticsearch</artifactId> <version>2.4.4</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> <dependency> <groupId>org.apache.storm</groupId> <artifactId>storm-core</artifactId> <version>1.0.2</version> <scope>provided</scope> </dependency> </dependencies> 3. Create an ElasticSearchOperation class in the com.stormadvance.storm_elasticsearch package.The ElasticSearchOperation class contains the following method: insert(Map<String, Object> data, String indexName, String indexMapping, String indexId): This method takes the record data, indexName, indexMapping, and indexId as input, and inserts the input record in Elasticsearch. The following is the source code of the ElasticSearchOperation class: public class ElasticSearchOperation { private TransportClient client; public ElasticSearchOperation(List<String> esNodes) throws Exception { try { Settings settings = Settings.settingsBuilder() .put("cluster.name", "elasticsearch").build(); client = TransportClient.builder().settings(settings).build(); for (String esNode : esNodes) { client.addTransportAddress(new InetSocketTransportAddress( InetAddress.getByName(esNode), 9300)); } } catch (Exception e) { throw e; } } public void insert(Map<String, Object> data, String indexName, String indexMapping, String indexId) { client.prepareIndex(indexName, indexMapping, indexId) .setSource(data).get(); } public static void main(String[] s){ try{ List<String> esNodes = new ArrayList<String>(); esNodes.add("127.0.0.1"); ElasticSearchOperation elasticSearchOperation = new ElasticSearchOperation(esNodes); Map<String, Object> data = new HashMap<String, Object>(); data.put("name", "name"); data.put("add", "add"); elasticSearchOperation.insert(data,"indexName","indexMapping",UUID. randomUUID().toString()); }catch(Exception e) { e.printStackTrace(); //System.out.println(e); } } } 4. Create a SampleSpout class in the com.stormadvance.stormhbase package. This class generates random records and passes them to the next action (bolt) in the topology. The following is the format of the record generated by the SampleSpout class: ["john","watson","abc"] The following is the source code of the SampleSpout class: public class SampleSpout extends BaseRichSpout { private static final long serialVersionUID = 1L; private SpoutOutputCollector spoutOutputCollector; private static final Map<Integer, String> FIRSTNAMEMAP = new HashMap<Integer, String>(); static { FIRSTNAMEMAP.put(0, "john"); FIRSTNAMEMAP.put(1, "nick"); FIRSTNAMEMAP.put(2, "mick"); FIRSTNAMEMAP.put(3, "tom"); FIRSTNAMEMAP.put(4, "jerry"); } private static final Map<Integer, String> LASTNAME = new   HashMap<Integer, String>(); static { LASTNAME.put(0, "anderson"); LASTNAME.put(1, "watson"); LASTNAME.put(2, "ponting"); LASTNAME.put(3, "dravid"); LASTNAME.put(4, "lara"); } private static final Map<Integer, String> COMPANYNAME = new HashMap<Integer, String>(); static { COMPANYNAME.put(0, "abc"); COMPANYNAME.put(1, "dfg"); COMPANYNAME.put(2, "pqr"); COMPANYNAME.put(3, "ecd"); COMPANYNAME.put(4, "awe"); } public void open(Map conf, TopologyContext context, SpoutOutputCollector spoutOutputCollector) { // Open the spout this.spoutOutputCollector = spoutOutputCollector; } public void nextTuple() { // Storm cluster repeatedly call this method to emit the continuous // // stream of tuples. final Random rand = new Random(); // generate the random number from 0 to 4. int randomNumber = rand.nextInt(5); spoutOutputCollector.emit (new Values(FIRSTNAMEMAP.get(randomNumber),LASTNAME.get(randomNumber),CO MPANYNAME.get(randomNumber))); } public void declareOutputFields(OutputFieldsDeclarer declarer) { // emits the field   firstName , lastName and companyName. declarer.declare(new Fields("firstName","lastName","companyName")); } } 5. Create an ESBolt class in the com.stormadvance.storm_elasticsearch package. This bolt receives the tuples emitted by the SampleSpout class, converts it to the Map structure, and then calls the insert() method of the ElasticSearchOperation class to insert the record into Elasticsearch. The following is the source code of the ESBolt class: public class ESBolt implements IBasicBolt { private static final long serialVersionUID = 2L; private ElasticSearchOperation elasticSearchOperation; private List<String> esNodes; /** * * @param esNodes */ public ESBolt(List<String> esNodes) { this.esNodes = esNodes; } public void execute(Tuple input, BasicOutputCollector collector) { Map<String, Object> personalMap = new HashMap<String, Object>(); // "firstName","lastName","companyName") personalMap.put("firstName", input.getValueByField("firstName")); personalMap.put("lastName", input.getValueByField("lastName")); personalMap.put("companyName", input.getValueByField("companyName")); elasticSearchOperation.insert(personalMap,"person","personmapping", UUID.randomUUID().toString()); } public void declareOutputFields(OutputFieldsDeclarer declarer) { } public Map<String, Object> getComponentConfiguration() { // TODO Auto-generated method stub return null; } public void prepare(Map stormConf, TopologyContext context) { try { // create the instance of ESOperations class elasticSearchOperation = new  ElasticSearchOperation(esNodes); } catch (Exception e) { throw new RuntimeException(); } } public void cleanup() { } } 6.  Create an ESTopology class in the com.stormadvance.storm_elasticsearch package. This class creates an instance of the spout and bolt classes and chains them together using a TopologyBuilder class. The following is the implementation of the main class: public class ESTopology { public static void main(String[] args) throws AlreadyAliveException, InvalidTopologyException { TopologyBuilder builder = new TopologyBuilder(); //ES Node list List<String> esNodes = new ArrayList<String>(); esNodes.add("10.191.209.14"); // set the spout class builder.setSpout("spout", new SampleSpout(), 2); // set the ES bolt class builder.setBolt("bolt", new ESBolt(esNodes), 2) .shuffleGrouping("spout"); Config conf = new Config(); conf.setDebug(true); // create an instance of LocalCluster class for // executing topology in local mode. LocalCluster cluster = new LocalCluster(); // ESTopology is the name of submitted topology. cluster.submitTopology("ESTopology", conf, builder.createTopology()); try { Thread.sleep(60000); } catch (Exception exception) { System.out.println("Thread interrupted exception : " + exception); } System.out.println("Stopped Called : "); // kill the LearningStormTopology cluster.killTopology("StormHBaseTopology"); // shutdown the storm test cluster cluster.shutdown(); } } To summarize we covered how we can store the data processed by Apache Storm into Elasticsearch by making the connection with Elasticsearch nodes inside the Storm bolts. If you enjoyed this post, check out the book Mastering Apache Storm to know more about different types of real time processing techniques used to create distributed applications.
Read more
  • 0
  • 0
  • 11609
article-image-creating-weapons-your-game-using-unrealscript
Packt
23 Apr 2013
18 min read
Save for later

Creating weapons for your game using UnrealScript

Packt
23 Apr 2013
18 min read
(For more resources related to this topic, see here.) Creating a gun that fires homing missiles UDK already has a homing rocket launcher packaged with the dev kit (UTWeap_ RocketLauncher). The problem however, is that it isn't documented well; it has a ton of excess code only necessary for multiplayer games played over a network, and can only lock on when you have loaded three rockets. We're going to change all of that, and allow our homing weapon to lock onto a pawn and fire any projectile of our choice. We also need to change a few functions, so that our weapon fires from the correct location and uses the pawn's rotation and not the camera's. Getting ready As I mentioned earlier, our main weapon for this article will extend from the UTWeap_ ShockRifle, as that gun offers a ton of great base functionality which we can build from. Let's start by opening your IDE and creating a new weapon called MyWeapon, and have it extend from UTWeap_ShockRifle as shown as follows: class MyWeapon extends UTWeap_ShockRifle; How to do it... We need to start by adding all of the variables that we'll be needing for our lock on feature. There are quite a few here, but they're all commented in pretty great detail. Much of this code is straight from UDK's rocket launcher, that is why it looks familiar. In this recipe, we'll be creating a base weapon which extends from one of the Unreal Tournament's most commonly used weapons, the shock rifle, and base all of our weapons from that. I've gone ahead and removed an unnecessary information, added comments, and altered functionality so that we can lock onto pawns with any weapon, and fire only one missile while doing so. /********************************************************* Weapon lock on support********************************************************//** Class of the rocket to use when seeking */var class<UTProjectile> SeekingRocketClass;/** The frequency with which we will check for a lock */var(Locking) float LockCheckTime;/** How far out should we be considering actors for a lock */var float LockRange;/** How long does the player need to target an actor to lock on toit*/var(Locking) float LockAcquireTime;/** Once locked, how long can the player go without painting theobject before they lose the lock */var(Locking) float LockTolerance;/** When true, this weapon is locked on target */var bool bLockedOnTarget;/** What "target" is this weapon locked on to */var Actor LockedTarget;var PlayerReplicationInfo LockedTargetPRI;/** What "target" is current pending to be locked on to */var Actor PendingLockedTarget;/** How long since the Lock Target has been valid */var float LastLockedOnTime;/** When did the pending Target become valid */var float PendingLockedTargetTime;/** When was the last time we had a valid target */var float LastValidTargetTime;/** angle for locking for lock targets */var float LockAim;/** angle for locking for lock targets when on Console */var float ConsoleLockAim;/** Sound Effects to play when Locking */var SoundCue LockAcquiredSound;var SoundCue LockLostSound;/** If true, weapon will try to lock onto targets */var bool bTargetLockingActive;/** Last time target lock was checked */var float LastTargetLockCheckTime; With our variables in place, we can now move onto the weapon's functionality. The InstantFireStartTrace() function is the same function we added in our weapon. It allows our weapon to start its trace from the correct location using the GetPhysicalFireStartLoc() function. function. As mentioned before, this simply grabs the rotation of the weapon's muzzle flash socket, and tells the weapon to fire projectiles from that location, using the socket's rotation. The same goes for GetEffectLocation(), which is where our muzzle flash will occur. The v in vector for the InstantFireStartTrace() function is not capitalized. The reason being that vector is actually of struct type, and not a function, and that is standard procedure in UDK. /********************************************************* Overriden to use GetPhysicalFireStartLoc() instead of* Instigator.GetWeaponStartTraceLocation()* @returns position of trace start for instantfire()********************************************************/simulated function vector InstantFireStartTrace(){return GetPhysicalFireStartLoc();}/********************************************************* Location that projectiles will spawn from. Works for secondaryfire on* third person mesh********************************************************/simulated function vector GetPhysicalFireStartLoc(optional vectorAimDir){Local SkeletalMeshComponent AttachedMesh;local vector SocketLocation;Local TutorialPawn TutPawn;TutPawn = TutorialPawn(Owner);AttachedMesh = TutPawn.CurrentWeaponAttachment.Mesh;/** Check to prevent log spam, and the odd situation winwhich a cast to type TutPawn can fail */if (TutPawn != none){AttachedMesh.GetSocketWorldLocationAndRotation(MuzzleFlashSocket, SocketLocation);}return SocketLocation;}/********************************************************* Overridden from UTWeapon.uc* @return the location + offset from which to spawn effects(primarily tracers)********************************************************/simulated function vector GetEffectLocation(){Local SkeletalMeshComponent AttachedMesh;local vector SocketLocation;Local TutorialPawn TutPawn;TutPawn = TutorialPawn(Owner);AttachedMesh = TutPawn.CurrentWeaponAttachment.Mesh;if (TutPawn != none){AttachedMesh.GetSocketWorldLocationAndRotation(MuzzleFlashSocket, SocketLocation);}MuzzleFlashSocket, SocketLocation);return SocketLocation;} Now we're ready to dive into the parts of code that are applicable to the actual homing of the weapon. Let's start by adding our debug info, which allows us to troubleshoot any issues we may have along the way. ********************************************************** Prints debug info for the weapon********************************************************/simulated function GetWeaponDebug( out Array<String> DebugInfo ){Super.GetWeaponDebug(DebugInfo);DebugInfo[DebugInfo.Length] = "Locked:"@bLockedOnTarget@LockedTarget@LastLockedontime@(WorldInfo.TimeSeconds-LastLockedOnTime);DebugInfo[DebugInfo.Length] ="Pending:"@PendingLockedTarget@PendingLockedTargetTime@WorldInfo.TimeSeconds;} Here we are simply stating which target our weapon is currently locked onto, in addition to the pending target. It does this by grabbing the variables we've listed before, after they've returned from their functions, which we'll add in the next part. We need to have a default state for our weapon to begin with, so we mark it as inactive. /********************************************************* Default state. Go back to prev state, and don't use our* current tick********************************************************/auto simulated state Inactive{ignores Tick;simulated function BeginState(name PreviousStateName){Super.BeginState(PreviousStateName);// not looking to lock onto a targetbTargetLockingActive = false;// Don't adjust our target lockAdjustLockTarget(None);} We ignore the tick which tells the weapon to stop updating any of its homing functions. Additionally, we tell it not to look for an active target or adjust its current target, if we did have one at the moment. While on the topic of states, if we finish our current one, then it's time to move onto the next: /********************************************************* Finish current state, & prepare for the next one********************************************************/simulated function EndState(Name NextStateName){Super.EndState(NextStateName);// If true, weapon will try to lock onto targetsbTargetLockingActive = true;}} If our weapon is destroyed or we are destroyed, then we want to prevent the weapon from continuing to lock onto a target. /********************************************************* If the weapon is destroyed, cancel any target lock********************************************************/simulated event Destroyed(){// Used to adjust the LockTarget.AdjustLockTarget(none);//Calls the previously defined Destroyed functionsuper.Destroyed();} Our next chunk of code is pretty large, but don't let it intimidate you. Take your time and read it through to have a thorough understanding of what is occurring. When it all boils down, the CheckTargetLock() function verifies that we've actually locked onto our target. We start by checking that we have a pawn, a player controller, and that we are using a weapon which can lock onto a target. We then check if we can lock onto the target, and if it is possible, we do it. At the moment we only have the ability to lock onto pawns. /****************************************************************** Have we locked onto our target?****************************************************************/function CheckTargetLock(){local Actor BestTarget, HitActor, TA;local UDKBot BotController;local vector StartTrace, EndTrace, Aim, HitLocation,HitNormal;local rotator AimRot;local float BestAim, BestDist;if((Instigator == None)||(Instigator.Controller ==None)||(self != Instigator.Weapon) ){return;}if ( Instigator.bNoWeaponFiring)// TRUE indicates that weapon firing is disabled for thispawn{// Used to adjust the LockTarget.AdjustLockTarget(None);// "target" is current pending to be locked on toPendingLockedTarget = None;return;}// We don't have a targetBestTarget = None;BotController = UDKBot(Instigator.Controller);// If there is BotController...if ( BotController != None ){// only try locking onto bot's targetif((BotController.Focus != None) &&CanLockOnTo(BotController.Focus) ){// make sure bot can hit itBotController.GetPlayerViewPoint( StartTrace, AimRot );Aim = vector(AimRot);if((Aim dot Normal(BotController.Focus.Location -StartTrace)) > LockAim ){HitActor = Trace(HitLocation, HitNormal,BotController.Focus.Location, StartTrace, true,,,TRACEFLAG_Bullet);if((HitActor == None)||(HitActor == BotController.Focus) ){// Actor being looked atBestTarget = BotController.Focus;}}}} Immediately after that, we do a trace to see if our missile can hit the target, and check for anything that may be in the way. If we determine that we can't hit our target then it's time to start looking for a new one. else{// Trace the shot to see if it hits anyoneInstigator.Controller.GetPlayerViewPoint( StartTrace, AimRot );Aim = vector(AimRot);// Where our trace stopsEndTrace = StartTrace + Aim * LockRange;HitActor = Trace(HitLocation, HitNormal, EndTrace, StartTrace,true,,, TRACEFLAG_Bullet);// Check for a hitif((HitActor == None)||!CanLockOnTo(HitActor) ){/** We didn't hit a valid target? Controllerattempts to pick a good target */BestAim = ((UDKPlayerController(Instigator.Controller)!=None)&&UDKPlayerController(Instigator.Controller).bConsolePlayer) ? ConsoleLockAim : LockAim;BestDist = 0.0;TA = Instigator.Controller.PickTarget(class'Pawn', BestAim, BestDist, Aim, StartTrace,LockRange);if ( TA != None && CanLockOnTo(TA) ){/** Best target is the target we've locked */BestTarget = TA;}}// We hit a valid targetelse{// Best Target is the one we've done a trace onBestTarget = HitActor;}} If we have a possible target, then we note its time mark for locking onto it. If we can lock onto it, then start the timer. The timer can be adjusted in the default properties and determines how long we need to track our target before we have a solid lock. // If we have a "possible" target, note its time markif ( BestTarget != None ){LastValidTargetTime = WorldInfo.TimeSeconds;// If we're locked onto our best targetif ( BestTarget == LockedTarget ){/** Set the LLOT to the time in seconds sincelevel began play */LastLockedOnTime = WorldInfo.TimeSeconds;} Once we have a good target, it should turn into our current one, and start our lock on it. If we've been tracking it for enough time with our crosshair (PendingLockedTargetTime), then lock onto it. else{if ( LockedTarget != None&&((WorldInfo.TimeSeconds - LastLockedOnTime >LockTolerance)||!CanLockOnTo(LockedTarget)) ){// Invalidate the current locked TargetAdjustLockTarget(None);}/** We have our best target, see if they shouldbecome our current target Check for a newpending lock */if (PendingLockedTarget != BestTarget){PendingLockedTarget = BestTarget;PendingLockedTargetTime =((Vehicle(PendingLockedTarget) != None)&&(UDKPlayerController(Instigator.Controller)!=None)&&UDKPlayerController(Instigator.Controller).bConsolePlayer)? WorldInfo.TimeSeconds + 0.5*LockAcquireTime: WorldInfo.TimeSeconds + LockAcquireTime;}/** Otherwise check to see if we have beentracking the pending lock long enough */else if (PendingLockedTarget == BestTarget&& WorldInfo.TimeSeconds = PendingLockedTargetTime ){AdjustLockTarget(PendingLockedTarget);LastLockedOnTime = WorldInfo.TimeSeconds;PendingLockedTarget = None;PendingLockedTargetTime = 0.0;}}} Otherwise, if we can't lock onto our current or our pending target, then cancel our current target, along with our pending target. else{if ( LockedTarget != None&&((WorldInfo.TimeSeconds -LastLockedOnTime > LockTolerance)||!CanLockOnTo(LockedTarget)) ){// Invalidate the current locked TargetAdjustLockTarget(None);}// Next attempt to invalidate the Pending Targetif ( PendingLockedTarget != None&&((WorldInfo.TimeSeconds - LastValidTargetTime >LockTolerance)||!CanLockOnTo(PendingLockedTarget)) ){// We are not pending another target to lock ontoPendingLockedTarget = None;}}} That was quite a bit to digest. Don't worry, because the functions from here on out are pretty simple and straightforward. As with most other classes, we need a Tick() function to check for something in each frame. Here, we'll be checking whether or not we have a target locked in each frame, as well as setting our LastTargetLockCheckTime to the number of seconds passed during game-time. /********************************************************* Check target locking with each update********************************************************/event Tick( Float DeltaTime ){if ( bTargetLockingActive && ( WorldInfo.TimeSeconds >LastTargetLockCheckTime + LockCheckTime ) ){LastTargetLockCheckTime = WorldInfo.TimeSeconds;// Time, in seconds, since level began playCheckTargetLock();// Checks to see if we are locked on a target}} As I mentioned earlier, we can only lock onto pawns. Therefore, we need a function to check whether or not our target is a pawn. /********************************************************* Given an potential target TA determine if we can lock on to it.By* default, we can only lock on to pawns.********************************************************/simulated function bool CanLockOnTo(Actor TA){if ( (TA == None) || !TA.bProjTarget || TA.bDeleteMe ||(Pawn(TA) == None) || (TA == Instigator) ||(Pawn(TA).Health <= 0) ){return false;}return ( (WorldInfo.Game == None) ||!WorldInfo.Game.bTeamGame || (WorldInfo.GRI == None) ||!WorldInfo.GRI.OnSameTeam(Instigator,TA) );} Once we have a locked target we need to trigger a sound, so that the player is aware of the lock. The whole first half of this function simply sets two variables to not have a target, and also plays a sound cue to notify the player that we've lost track of our target. /********************************************************* Used to adjust the LockTarget.********************************************************/function AdjustLockTarget(actor NewLockTarget){if ( LockedTarget == NewLockTarget ){// No need to updatereturn;}if (NewLockTarget == None){// Clear the lockif (bLockedOnTarget){// No targetLockedTarget = None;// Not locked onto a targetbLockedOnTarget = false;if (LockLostSound != None && Instigator != None &&Instigator.IsHumanControlled() ){// Play the LockLostSound if we lost track of thetargetPlayerController(Instigator.Controller).ClientPlaySound(LockLostSound);}}}else{// Set the lockbLockedOnTarget = true;LockedTarget = NewLockTarget;LockedTargetPRI = (Pawn(NewLockTarget) != None) ?Pawn(NewLockTarget).PlayerReplicationInfo : None;if ( LockAcquiredSound != None && Instigator != None &&Instigator.IsHumanControlled() ){PlayerController(Instigator.Controller).ClientPlaySound(LockAcquiredSound);}}} Once it looks like everything has checked out we can fire our ammo! We're just setting everything back to 0 at this point, as our projectile is seeking our target, so it's time to start over and see whether we will use the same target or find another one. /********************************************************* Everything looks good, so fire our ammo!********************************************************/simulated function FireAmmunition(){Super.FireAmmunition();AdjustLockTarget(None);LastValidTargetTime = 0;PendingLockedTarget = None;LastLockedOnTime = 0;PendingLockedTargetTime = 0;} With all of that out of the way, we can finally work on firing our projectile, or in our case, our missile. ProjectileFile() tells our missile to go after our currently locked target, by setting the SeekTarget variable to our currently locked target. /********************************************************* If locked on, we need to set the Seeking projectile's* LockedTarget.********************************************************/simulated function Projectile ProjectileFire(){local Projectile SpawnedProjectile;SpawnedProjectile = super.ProjectileFire();if (bLockedOnTarget &&UTProj_SeekingRocket(SpawnedProjectile) != None){/** Go after the target we are currently lockedonto */UTProj_SeekingRocket(SpawnedProjectile).SeekTarget =LockedTarget;}return SpawnedProjectile;} Really though, our projectile could be anything at this point. We need to tell our weapon to actually use our missile (or rocket, they are used interchangeably) which we will define in our defaultproperties block. /********************************************************* We override GetProjectileClass to swap in a Seeking Rocket if weare* locked on.********************************************************/function class<Projectile> GetProjectileClass(){// if we're locked on...if (bLockedOnTarget){// use our homing rocketreturn SeekingRocketClass;}// Otherwise...else{// Use our default projectilereturn WeaponProjectiles[CurrentFireMode];}} If we don't have a SeekingRocketClass class defined, then we just use the currently defined projectile from our CurrentFireMode array. The last part of this class involves the defaultproperties block. This is the same thing we saw in our Camera class. We're setting our muzzle flash socket, which is used for not only firing effects, but also weapon traces, to actually use our muzzle flash socket. defaultproperties{// Forces the secondary fire projectile to fire fromthe weapon attachment */MuzzleFlashSocket=MuzzleFlashSocket} Our MyWeapon class is complete. We don't want to clog our defaultproperties block and we have some great base functionality, so from here on out our weapon classes will generally be only changes to the defaultproperties block. Simplicity! Create a new class called MyWeapon_HomingRocket. Have it extend from MyWeapon. class MyWeapon_HomingRocket extends MyWeapon; In our defaultproperties block, let's add our skeletal and static meshes. We're just going to keep using the shock rifle mesh. Although it's not necessary to do this, as we're already a child class of (that is, inheriting from) UTWeap_ShockRifle, I still want you to see where you would change the mesh if you ever wanted to. defaultproperties{// Weapon SkeletalMeshBegin Object class=AnimNodeSequence Name=MeshSequenceAEnd Object// Weapon SkeletalMeshBegin Object Name=FirstPersonMeshSkeletalMesh=SkeletalMesh'WP_ShockRifle.Mesh.SK_WP_ShockRifle_1P'AnimSets(0)=AnimSet'WP_ShockRifle.Anim.K_WP_ShockRifle_1P_Base'Animations=MeshSequenceARotation=(Yaw=-16384)FOV=60.0End Object// PickupMeshBegin Object Name=PickupMeshSkeletalMesh=SkeletalMesh'WP_ShockRifle.Mesh.SK_WP_ShockRifle_3P'End Object// Attachment classAttachmentClass=class'UTGameContent.UTAttachment_ShockRifle' Next, we want to declare the type of projectile, the type of damage it does, and the frequency at which it can be fired. Moreover, we want to declare that each shot fired will only deplete one round from our inventory. We can declare how much ammo the weapon starts with too. // Defines the type of fire for each modeWeaponFireTypes(0)=EWFT_InstantHitWeaponFireTypes(1)=EWFT_ProjectileWeaponProjectiles(1)=class'UTProj_Rocket'// Damage typesInstantHitDamage(0)=45FireInterval(0)=+1.0FireInterval(1)=+1.3InstantHitDamageTypes(0)=class'UTDmgType_ShockPrimary'InstantHitDamageTypes(1)=None// Not an instant hit weapon, so set to "None"// How much ammo will each shot use?ShotCost(0)=1ShotCost(1)=1// # of ammo gun should start withAmmoCount=20// Initial ammo count if weapon is lockedLockerAmmoCount=20// Max ammo countMaxAmmoCount=40 Our weapon will use a number of sounds that we didn't previously need, such as locking onto a pawn, as well as losing lock. So let's add those now. // Sound effectsWeaponFireSnd[0] =SoundCue'A_Weapon_ShockRifle.Cue.A_Weapon_SR_FireCue'WeaponFireSnd[1]=SoundCue'A_Weapon_RocketLauncher.Cue.A_Weapon_RL_Fire_Cue'WeaponEquipSnd=SoundCue'A_Weapon_ShockRifle.Cue.A_Weapon_SR_RaiseCue'WeaponPutDownSnd=SoundCue'A_Weapon_ShockRifle.Cue.A_Weapon_SR_LowerCue'PickupSound=SoundCue'A_Pickups.Weapons.Cue.A_Pickup_Weapons_Shock_Cue'LockAcquiredSound=SoundCue'A_Weapon_RocketLauncher.Cue.A_Weapon_RL_SeekLock_Cue'LockLostSound=SoundCue'A_Weapon_RocketLauncher.Cue.A_Weapon_RL_SeekLost_Cue' We won't be the only one to use this weapon, as bots will be picking it up during Deathmatch style games as well. Therefore, we want to declare some logic for the bots, such as how strongly they will desire it, and whether or not they can use it for things like sniping. // AI logicMaxDesireability=0.65 // Max desireability for botsAIRating=0.65CurrentRating=0.65bInstantHit=false // Is it an instant hit weapon?bSplashJump=false// Can a bot use this for splash damage?bRecommendSplashDamage=true// Could a bot snipe with this?bSniping=false// Should it fire when the mouse is released?ShouldFireOnRelease(0)=0// Should it fire when the mouse is released?ShouldFireOnRelease(1)=0 We need to create an offset for the camera too, otherwise the weapon wouldn't display correctly as we switch between first and third person cameras. // Holds an offset for spawning projectile effectsFireOffset=(X=20,Y=5)// Offset from view center (first person)PlayerViewOffset=(X=17,Y=10.0,Z=-8.0) Our homing properties section is the bread and butter of our class. This is where you'll alter the default values for anything to do with locking onto pawns. // Homing properties/** angle for locking for locktargets when on Console */ConsoleLockAim=0.992/** How far out should we be before considering actors fora lock? */LockRange=9000// Angle for locking, for lockTargetLockAim=0.997// How often we check for lockLockChecktime=0.1// How long does player need to hover over actor to lock?LockAcquireTime=.3// How close does the trace need to be to the actual targetLockTolerance=0.8SeekingRocketClass=class'UTProj_SeekingRocket' Animations are an essential part of realism, so we want the camera to shake when firing a weapon, in addition to an animation for the weapon itself. // camera anim to play when firing (for camera shakes)FireCameraAnim(1)=CameraAnim'Camera_FX.ShockRifle.C_WP_ShockRifle_Alt_Fire_Shake'// Animation to play when the weapon is firedWeaponFireAnim(1)=WeaponAltFire While we're on the topic of visuals, we may as well add the flashes at the muzzle, as well as the crosshairs for the weapon. // Muzzle flashesMuzzleFlashPSCTemplate=WP_ShockRifle.Particles.P_ShockRifle_MF_AltMuzzleFlashAltPSCTemplate=WP_ShockRifle.Particles.P_ShockRifle_MF_AltMuzzleFlashColor=(R=200,G=120,B=255,A=255)MuzzleFlashDuration=0.33MuzzleFlashLightClass=class'UTGame.UTShockMuzzleFlashLight'CrossHairCoordinates=(U=256,V=0,UL=64,VL=64)LockerRotation=(Pitch=32768,Roll=16384)// CrosshairIconCoordinates=(U=728,V=382,UL=162,VL=45)IconX=400IconY=129IconWidth=22IconHeight=48/** The Color used when drawing the Weapon's Name on theHUD */WeaponColor=(R=160,G=0,B=255,A=255) Since weapons are part of a pawn's inventory, we need to declare which slot this weapon will fall into (from one to nine). // InventoryInventoryGroup=4 // The weapon/inventory set, 0-9GroupWeight=0.5 // position within inventory group.(used by prevweapon and nextweapon) Our final piece of code has to do with rumble feedback with the Xbox gamepad. This is not only used on consoles, but also it is generally reserved for it. /** Manages the waveform data for a forcefeedback device,specifically for the xbox gamepads. */Begin Object Class=ForceFeedbackWaveformName=ForceFeedbackWaveformShooting1Samples(0)=(LeftAmplitude=90,RightAmplitude=40,LeftFunction=WF_Constant,RightFunction=WF_LinearDecreasing,Duration=0.1200)End Object// controller rumble to play when firingWeaponFireWaveForm=ForceFeedbackWaveformShooting1} All that's left to do is to add the weapon to your pawn's default inventory. You can easily do this by adding the following line to your TutorialGame class's defaultproperties block: defaultproperties{DefaultInventory(0)=class'MyWeapon_HomingRocket'} Load up your map with a few bots on it, hold your aiming reticule over it for a brief moment and when you hear the lock sound, fire away! How it works... To keep things simple we extend from UTWeap_ShockRifle. This gave us a great bit of base functionality to work from. We created a MyWeapon class which offers not only everything that the shock rifle does, but also the ability to lock onto targets. When we aim our target reticule over an enemy bot, it checks for a number of things. First, it verifies that it is an enemy and also whether or not the target can be reached. It does this by drawing a trace and returns any actors which may fall in our weapon's path. If all of these things check out, then it begins to lock onto our target after we've held the reticule over the enemy for a set period of time. We then fire our projectile, which is either the weapon's firing mode, or in our case, a rocket. We didn't want to clutter the defaultproperties block for MyWeapon; so we create a child class called MyWeapon_HomingRocket that makes use of all the functionality and only changes the defaultproperties block, which will influence the weapon's aesthetics, sound effects, and even some functionality with the target lock.
Read more
  • 0
  • 0
  • 11594

article-image-democratizing-ai-with-stability-ais-initiative-stablelm
Julian Melanson
22 Jun 2023
6 min read
Save for later

Democratizing AI with Stability AI’s Initiative, StableLM

Julian Melanson
22 Jun 2023
6 min read
Artificial Intelligence is becoming a cornerstone of modern technology, transforming our work, lives, and communication. However, its development has largely remained in the domain of a handful of tech giants, limiting accessibility for smaller developers or independent researchers. A potential shift in this paradigm is visible in Stability AI's initiative - StableLM, an open-source language model aspiring to democratize AI. Developed by Stability AI, StableLM leverages a colossal dataset, "The Pile," comprising 1.5 trillion tokens of content. It encompasses models with parameters from 3 billion to 175 billion, facilitating diverse research and commercial applications. Furthermore, this open-source language model employs an assortment of datasets from recent models like Alpaca, GPT4All, Dolly, ShareGPT, and HH for fine-tuning.StableLM represents a paradigm shift towards a more inclusive and universally accessible AI technology. In a bid to challenge dominant AI players and foster innovation, Stability AI plans to launch StableChat, a chat model devised to compete with OpenAI's ChatGPT. The democratization of AI isn't a novel endeavor for Stability AI. Their earlier project, Stable Diffusion, an open-source alternative to OpenAI’s DALL-E 2, rejuvenated the generative content market and spurred the conception of new business ideas. This accomplishment set the stage for the launch of StableLM in a market rife with competition.Comparing StableLM with models like ChatGPT and LLama reveals unique advantages. While both ChatGPT and StableLM are designed for natural language processing (NLP) tasks, StableLM emphasizes transparency and accessibility. ChatGPT, developed by OpenAI, boasts a parameter count of 1 trillion, far exceeding StableLM's highest count of 175 billion. Furthermore, using ChatGPT entails costs, unlike the open-source StableLM. On the other hand, LLama, another open-source language model, relies on a different training dataset than StableLM's "The Pile." Regardless of the disparities, all three models present valuable alternatives for AI practitioners.A potential partnership with AWS Bedrock, a platform providing a standard approach to building, training, and deploying machine learning models, could bolster StableLM's utility. Integrating StableLM with AWS Bedrock's infrastructure could allow developers to leverage StableLM's performance and AWS Bedrock's robust tools.Enterprises favor open-source models like StableLM for their transparency, flexibility, and cost-effectiveness. These models promote rapid innovation, offer technology control, and lead to superior performance and targeted results. They are maintained by large developer communities, ensuring regular updates and continual innovation. StableLM demonstrates Stability AI's commitment to democratizing AI, and fostering diversity in the AI market. It brings forth a multitude of options, refined applications, and tools for users. The core of StableLM's value proposition lies in its dedication to transparency, accessibility, and user support.Following the 2022 public release of the Stable Diffusion model, Stability AI continued its mission to democratize AI with the introduction of the StableLM set of models. Trained on an experimental dataset three times larger than "The Pile," StableLM shows excellent performance in conversational and coding tasks, despite having fewer parameters than GPT-3. In addition to this, Stability AI has introduced research models optimized for academic research. These models utilize data from recently released open-source conversational agent datasets such as Alpaca, GPT4All, Dolly, ShareGPT, and HH.StableLM's vision revolves around fostering transparency, accessibility, and supportiveness. By focusing on enhancing AI's effectiveness in real-world tasks rather than chasing superhuman intelligence, Stability AI opens up innovative and practical applications of AI. This approach augments AI's potential to drive innovation, boost productivity, and expand economic prospects.A Guide to Installing StableLMStableLM can be installed using two different methods: one with a text generation web UI and the other with llama.cpp. Both of these methods provide a straightforward process for setting up StableLM on various operating systems including Windows, Linux, and macOS.Installing StableLM with Text Generation Web UIThe installation process with the one-click installer involves a simple three-step procedure that works across Windows, Linux, and macOS. First, download the zip file and extract it. Then double-click on "start". These zip files are provided directly by the web UI's developer. Following this, the model can be downloaded from Hugging Face, completing the installation process.Installing StableLM with llama.cppThe installation procedure with llama.cpp varies slightly between Windows and Linux/macOS. For Windows, start by downloading the latest release and extracting the zip file. Next, create a "models" folder inside the extracted folder. After this, download the model and place it inside the model's folder. Lastly, run the following command, replacing 'path\to' with the actual directory path of your files: 'path\to\main.exe -m models\7B\ggml-model-stablelm-tuned-alpha-7b-q4_0.bin -n 128'.For Linux and macOS, the procedure involves a series of commands run through the Terminal. Start by installing the necessary libraries with the'python3 -m pip install torch numpy sentencepiece'. Next, clone the llama.cpp repository from GitHub with 'git clone https://github.com/ggerganov/llama.cpp' and navigate to the llama.cpp directory with 'cd llama.cpp'. Compile the program with the 'make' command. Finally, download the pre-quantized model, or convert the original following the documentation provided in the llama.cpp GitHub page. To run StableLM, use the command './main -m ./models/7B/ggml-model-stablelm-tuned-alpha-7b-q4_0.bin -n 128'.In sum, StableLM's introduction signifies a considerable leap in democratizing AI. Stability AI is at the forefront of a new AI era characterized by openness, scalability, and transparency, widening AI's economic benefits and making it more inclusive and accessible.SummaryIn this article, we have introduced StabilityLM, a new language model that is specifically designed to be more stable and robust than previous models. We have shown how to install StabilityLM using the Text Generation Web UI, as well as by compiling the llama.cpp code. We have also discussed some of the benefits of using StabilityLM, such as its improved stability and its ability to generate more creative and informative text. StabilityLM can be used for a variety of tasks, including text generation, translation, and summarization.Overall, StabilityLM is a promising new language model that offers a number of advantages over previous models. If you are looking for a language model that is stable, robust, and creative, then StabilityLM is a good option to consider.Author BioJulian Melanson is one of the founders of Leap Year Learning. Leap Year Learning is a cutting-edge online school that specializes in teaching creative disciplines and integrating AI tools. We believe that creativity and AI are the keys to a successful future and our courses help equip students with the skills they need to succeed in a continuously evolving world. Our seasoned instructors bring real-world experience to the virtual classroom and our interactive lessons help students reinforce their learning with hands-on activities.No matter your background, from beginners to experts, hobbyists to professionals, Leap Year Learning is here to bring in the future of creativity, productivity, and learning!
Read more
  • 0
  • 0
  • 11591

article-image-setting-scans
Packt
04 Sep 2013
10 min read
Save for later

Setting up scans

Packt
04 Sep 2013
10 min read
(For more resources related to this topic, see here.) Setting up a scan in Spiceworks The first thing Spiceworks tries to do to scan a network is contact Active Directory(AD); it also uses AD to populate the People portion of your Inventory. Let's set up AD first, as everything else we will be configuring is on the same page. We are all about saving your time and not going back and forth between pages. If you do not have AD in your environment, you can just skip to the Configuring IP range scans section. Scanning and Active Directory There is a wealth of information within AD that Spiceworks uses. We are going to need to configure Spiceworks to log into AD and get that information. OK, we need to get to the Active Directory Configuration screen in Spiceworks in order to do that. As with most things within the app, it is just a couple of clicks. From anywhere in the app, mouse over the Inventory link at the top of the page; a menu will open up. Click on Settings. This will take us to the Settings screen. You will be spending a lot of time here so you can either get very used to these clicks or just have a separate tab open with these settings already set up. The top section is called Getting Started and the first link is Active Directory Configuration. That is our destination for this section so click away. It will take you to the Active Directory Configuration page: There are three sections that are highlighted. Let's go over each and what they do: The area highlighted as 1 is where you are going to enter the credentials that allow Spiceworks to log into your AD and get information. You specify the Active Directory Server (Domain Controller), username and password. Usernames must be in either domain/username or username@domain.com. If you have SSL enabled for AD inquiries, check the Use SSL box. The area highlighted as 2 shows the frequency at which Spiceworks retrieves information from your AD environment. When Spiceworks queries AD, it does not cause a huge amount of traffic or load. Shortening these times should not cause undue stress on your AD servers. This is useful because when you add a user in AD, it will automatically get loaded into Spiceworks at the next scan. If you want any changes you make to users in Spiceworks to be uploaded into your AD environment, the section highlighted as 3 is for you. Just click on the box and any modifications you make in Spiceworks will automatically be synchronized with your AD. There is one more section that is not in the screenshot. This deals with your user portal and help desk. Setting up AD in your Spiceworks really makes a lot of difference with scans and filling in information. It is recommended that if you are running AD, hook this up. If you are wary about Spiceworks writing data into your AD environment, just set up the user that Spiceworks uses to connect as read-only and don't check the box that writes changes back to AD. Easy enough. Since you are convinced that you should connect your AD to Spiceworks, just fill in the ActiveDirectory server, User, and Password fields and click on Save. Spiceworks will automatically test the credentials and let you know immediately if it can connect. If you have some challenges with Spiceworks connecting to your Domain Controller with just the server name, another method is to put the IP address directly into that field. Let's move on to setting up an IP range scan and get some devices into your Spiceworks install. Configuring IP range scans Remember the Settings page that we have been to a couple of times? We are going back! In case you have forgotten, just mouse over to either Inventory or Help Desk and click on the Settings link at the bottom of the left column. Once on the Settings page, we are going to click on the Network Scan link. It is in the first section of links titled Getting Started. This takes us to the main Network Scan page. The first section is where we are going to set up our IP ranges. Since you will not have any ranges in here as you just installed Spiceworks, let's get one configured so you can get some information into the app. To do this, just click on the Add IP Range button and this window will pop up. There is a lot of flexibility that Spiceworks gives you regarding how it scans IP ranges. You can put a fill range (192.168.1.1-254) with or without exclusions, or just a single IP if you so wish. The next box is for exclusions, if you so choose. If you decide you want to scan a range that has both servers and desktops, you can exclude server IP addresses. This is handy. The last options are for scheduling this IP range scan. If you choose the Daily at… option as we have seen in the screenshot, you can also select the time of the day to run this scan. Other options in this drop-down list are every 4, 6, 8, or 12 hours. If you do decide that you want to scan on an hourly basis, the time of the day magically disappears. The bottom of the window lets you select what days of the week you want to run the scan. When Spiceworks runs an initial scan, it can take a bit of time as there is a ton of data that it is collecting. Spiceworks tries a multitude of credentials and reads all information from devices, which it then writes to the database. Once Spiceworks has scanned and written the data to the database, any subsequent scans just write delta data into it. Enter what range you want to scan, any exclusions you choose, and the scan frequency, and click on the Add button. Congratulations! You have just added an IP range scan! Scanning credentials As we have covered, Spiceworks uses a multitude of credentials to try and figure out what is on your network and put those devices into the inventory. This has been completely overhauled in Spiceworks. In this easy-to-use interface, you can enter all the credentials that you are going to need to have a successful scan. Here you can configure multiple usernames/passwords for the following protocols: WMI SSH SNMP Enable ESX/vSphere HTTP iLo SNMP v2c/v3 Telnet Intel vPro As you can see, if you need to put device-specific usernames and passwords into Spiceworks, you can do so using the format, Domainusername. So if you have a server that uses a unique username/password combination, it is easy to set all that up through this interface. The preceding screenshot shows an example of this. Something new in Spiceworks is the section where it shows devices that the credentials were successfully used on. This is really helpful for troubleshooting any scan errors! To add your own username/password combinations, just use these easy-to-follow directions: Click on the protocol you want to add credentials to on the left column (WMI, SNMP, and so on). Click on +Add Account in the middle column labeled Existing Accounts. Enter all the pertinent information on the left pane labeled Edit Account.For usernames that have passwords, there is a Show Password button as well, so you can make sure that you didn't fat finger it! That's it. Just fill in any credentials that will let Spiceworks access your devices on your network, and as far as permissions are concerned you should be good to go! Best practices and kicking off your first Spiceworks scan You have everything you need to start your first Spiceworks scan. It might be best to read the following best practices before you kick it off, though. They will guide you through some potential pitfalls. Scanning best practices For initial scans, be aware of the number of IP addresses you are scanning and the amount of information that Spiceworks is going to pull out of those devices. If you put in a full IP range on your first scan, do not expect Spiceworks to be completed in 10-15 minutes. The initial scan is the most network traffic intensive and will take the longest duration of time. Do full initial scans during nonbusiness hours. Though running an initial full scan shouldn't flood your network, depending on your network configuration, it is always best to run full initial scans during nonbusiness hours just in case. If you are running a 24 x 7 business, break up your IP ranges into smaller chunks and scan that way. Expect some unknown devices. Unless you are a super administrator with a team of hundreds behind you to make sure that every aspect of your network is 100 percent buttoned down, there will most likely be a few devices that Spiceworks cannot connect to. One of the biggest culprits is that WMI has been disabled, or that there is a firewall of some sort blocking Spiceworks from connecting to the machine. Don't get down on yourself if the scan doesn't work 100 percent the first time. If you are really worried about traffic that Spiceworks might cause, what information it collects, or how it will affect workstation performance, just set up a test environment and run a scan there. Whether it be 5 machines or 500, Spiceworks does the same to each one; so test away. Spiceworks is not designed to scan 10,000 devices at one time without a performance hit. If you have a very large network, break it up into smaller chunks for best performance. Spiceworks could get through a 10,000 device scan, but it would hurt performance until the scan is complete. If you have multiple sites linked either by WAN or VPN connections, drop a remote collector at these to run local scans and then send the data back to your main Spiceworks installation. You can find more information at http://community.spiceworks.com/help/Remote_Collectors OK, now that you have read the required best practices, you can set up your IP range on the Network Scan settings page, check the box associated with that range and click on Start Scan. Away you go! Depending on the IP range you set and the time of the day, your scan could take just a few minutes or several hours. If you are having some serious issues trying to get a successful scan, open a browser and hit this site: http://community.spiceworks.com/support. There are in-depth articles and even real-live support folks that can dive into the specifics of your environment, and they won't give up until you are successful. Let's assume that even if you did have an issue, it is resolved and you have got your first scan under your belt. Summary We were provided with details on how to set up a scan in Spiceworks. Also, we got to know how to run the scan we set up and the best practices. Resources for Article : Further resources on this subject: Using SpriteFonts in a Board-based Game with XNA 4.0 [Article] Why CoffeeScript?HTML5 Games Development: Using Local Storage to Store Game Data [Article] Making Money with Your Game [Article]
Read more
  • 0
  • 0
  • 11583
article-image-working-tables
Packt
07 Sep 2015
13 min read
Save for later

Working with Tables

Packt
07 Sep 2015
13 min read
 In this article by the author, Chukri Soueidi, of the book, Microsoft Azure Storage Essentials, we learn about service offered by Microsoft Azure. The topic of this article will be Table storage. Tables provide scalable, structured data stores that allow you to store huge amounts of data. With the growing needs of modern high-performance applications, choosing the right data store is a major factor in the success of any application. (For more resources related to this topic, see here.) The Table storage basics Azure Table storage is a key/value NoSQL database that allows you to store non-relational, structured, and semi-structured data that does not have to conform to a specific schema. It is ideal for storing huge amounts of data that is ready for simple and quick read/write operations, and is interfaced by the Table REST API using the OData protocol. A table can contain one or many entities (rows), each up to 1 MB in size. The whole table cannot exceed a 100 TB limit. Each table entity can hold up to 252 columns. Rows in the same table can have different schemas, as opposed to relational database rows that should all comply under one strict schema. Table storage is structured in a hierarchical relationship between storage accounts, tables, and entities. A storage account can have a zero or more non-related tables, each containing one or more entities. The components of the service are: Storage account: Governs access to the underlying service Table: A collection of entities Entity: A set of properties, a row in the table Properties: Key/value pairs that can hold scalar data such as string, byte array, guid, dateTime, integer, double, boolean Table address: http://<account-name>.table.core.windows.net/<table-name > The address differs when using the Storage Emulator, which emulates the Table storage service locally without incurring any cost. The default address will be the local machine loopback address followed by a predefined default storage account name. It would look as follows: http://127.0.0.1:10002/devstorageaccount1/<table-name> For more on the Storage Emulator, you can check out the Use the Azure Storage Emulator for Development and Testing article on the Azure documentation. Entities Entities, in tables, are associated with two key properties: the PartitionKey and the RowKey, which together form the entity's primary key. The PartitionKey must be a string with a maximum allowed size of 1,024 characters. As its name suggests, it divides the table logically into partitions. Entities with the same partition key will be always stored in the same physical node, promoting performance and scalability. When a table scales up, the Azure platform may automatically move different partitions of a table into separate physical storage nodes for load balancing purposes. Entities with the same partition key stay on the same node no matter how much their table scales; hence, the key selection is essential in determining the general performance of the table. The second column is the RowKey, which is also of the string type, with a maximum allowed size of 1,024 characters. It has to be unique inside a partition, since the partition key and row key combine to uniquely identify an entity within the table. In addition to that, each entity has a read-only mandatory Timestamp property, which is essential for managing concurrent updates on records. Naming rules When naming tables and properties, there are some naming rules to follow: Tables: A table name should be unique per storage account, ranging from 3 to 63 characters long. It can only contain alphanumeric characters and cannot begin with a number. Table names are case-insensitive, but will reflect the case that was used upon creation. (Mytable and MyTable are logically the same name, but if you create a table called Mytable then Mytable—not MyTable—will be displayed when you retrieve table names from the account.) Properties: A property name is case-sensitive with a size of up to 255 characters. It should follow C# identifier naming rules. When passed within a URL, certain characters must be percent-encoded, which is automatically done when using the .NET Library. Some characters are disallowed in the values of the row and partition keys, including the back slash (), forward slash (/), the number sign (#) and the question mark (?). Using the Azure Storage Client Library The Azure Storage Client Library for .NET has classes to manage and maintain Table storage objects. After creating a storage account, and getting the appropriate account storage access keys, we now have everything it takes to use the storage service. For the simplicity of this demo's setup, we will be using a C# Console Application template. To create a Console Application open Visual Studio and navigate to New Project | Templates | Visual C# | Console Application. By default, the application does not have a reference to the storage client library, so we need to add it using the Package Manager by typing Install-Package WindowsAzure.Storage. This will download and install the library along with all dependencies required. You can navigate through the library by expanding References in Solution Explorer in Visual Studio, right-clicking on Microsoft.WindowsAzure.Storage, and selecting View in Object Browser. This will show you all library classes and methods. After getting the storage library, we need to create the connection string by providing the storage account name and access key. The connection string would look like this: <appSettings> <add key="StorageConnectionString" value="DefaultEndpointsProtocol=https;AccountName=account name;AccountKey=access key/> </appSettings> In program.cs we need to reference the following libraries: using System.Configuration; // reference to System.Configuration should be added to the project using Microsoft.WindowsAzure.Storage; using Microsoft.WindowsAzure.Storage.Table; Starting with a table Using the connection string defined in the App.config file, we will proceed to create a CloudStorageAccount object which represents the storage account where the tables will be created. After that we need to use the CloudTableClient class, which is defined under the Microsoft.WindowsAzure.Storage.Table namespace, to create an object which represents a frontage for dealing with Table storage specifically and directly. After creating the table object we will call its CreateIfNotExists() method that will actually call the Table REST API to create a table. The method is idempotent: if the table already exists, the method will do nothing no matter how many times you call it. The following is the code to do create a table: string connectionString = ConfigurationManager.AppSettings["StorageConnectionString"]; CloudStorageAccount storageAccount = CloudStorageAccount.Parse(connectionString); CloudTableClient tableClient = storageAccount.CreateCloudTableClient(); CloudTable table = tableClient.GetTableReference("Weather"); table.CreateIfNotExists(); A table can be deleted using the following code: table.DeleteIfExists(); We created a Weather table for the purpose of demonstrating a broader overview of Table storage features. Our sample is a table for saving the weather history of all the cities around the world. For each city, the table holds a weather entry per day and time. Assuming there are more than 200,000 cities and each city has 24 entries per day, the table will contain millions of records in no time. Adding entities to a table After creating the table, Weather, we need to populate it with entities. In the .NET library, entities are mapped to C# objects. The library defines the ITableEntity interface which should be implemented by all classes representing entities. The ITableEntity interface defines the following properties: PartitionKey: It is a string for the partition key of the an entity RowKey: It is a string for the row key Timestamp: It is a DateTime offset for the last update on the entity ETag: It is an entity tag for managing concurrency The library also contains two classes that implement ITableEntity. The TableEntity is a base class that can be inherited by custom classes. The DynamicTableEntity is a class that holds an IDictionary<String,EntityProperty> property named Properties that is used to store properties inside it. Now, let's define our custom entity by inheriting from the TableEntity base class: public class WeatherEntity : TableEntity { public WeatherEntity(string cityId, string daytime) { this.PartitionKey = cityId; this.RowKey = daytime; } public WeatherEntity() { } public string CityName { get; set; } public string CountryCode { get; set; } public string Description { get; set; } public string Temperature { get; set; } public string Humidity { get; set; } public string Wind { get; set; } } In the preceding code, we have defined the Weather entity class with a constructor that takes the arguments of cityId and a string representing the day and time, which we chose to declare as PartitionKey and RowKey, respectively; since the entity should inherit from a TableEntity class, we assign the keys to the base class properties using this. The partition and row key selection was based on the table's querying needs. The PartitionKey is selected to be the cityId, and the RowKey is a string representation of the date and time in the format "yyyyMMddHHmm". Now, after defining the entity as an object, we will proceed to add the entity to the WeatherHistory table. First we have to create an instance of this object and populate its properties, then hand it to a TableOperation object to insert it in to our table. The following is the code for this: WeatherEntity weather = new WeatherEntity("5809844", "201503151200") { CityName = "Seattle", CountryCode = "US", Description = "Clear", Temperature = "25.5", Humidity = "44", Wind = "11 km/h", };   TableOperation insertOperation = TableOperation.Insert (weather);   table.Execute (insertOperation); The TableOperation class represents a single table operation. In addition to the insert operation, this class defines the static merge, replace, and delete, and other methods that we will see later on. After creating the operation, we pass it to the Execute method of the CloudTable table entity, which represents the Weather table. The Timestamp property of the entity is required, but we did not set it in our code. This is because this property will be filled by the server automatically; even if we set it the server will rewrite its own timestamp. Entity Group Transactions In case we have several entities to insert into the table, we have the option to perform a batch operation that can insert many records in one group transaction. We can use the TableBatchOperation and add the entities to it, then perform the CloudTable.ExecuteBatch. The following is some sample code to add two weathers at the same time: TableBatchOperation batchOperation = new TableBatchOperation(); WeatherEntity weather1 = new WeatherEntity("5809844", "201503151300") { CityName = "Seattle", CountryCode = "US", Description = "Light Rain", Temperature = "23", Humidity = "82", Wind = "16 km/h", }; WeatherEntity weather2 = new WeatherEntity("5809844", "201503151400") { CityName = "Seattle", CountryCode = "US", Description = "Heavy Rain", Temperature = "20", Humidity = "95", Wind = "16 km/h", }; batchOperation.Insert(weather1); batchOperation.Insert(weather2); table.ExecuteBatch(batchOperation); The following is a sample of how the table will look when it contains records for several days and cities; we omitted the timestamp for the clarity of the sample: PartitionKey RowKey City Country Description   Humidity Wind … … … … … … … … 276781 201503151300 Beirut LB Clear 25 65 5 km/h 276781 201503151400 Beirut LB Clear 26 65 5 km/h 5128638 201503151300 New York US Sunny 25 46 11 km/h 5128638 201503151400 New York US Few clouds 25 46 11 km/h 5809844 201503151300 Seattle US Light rain 23 82 16 km/h 5809844 201503151400 Seattle US Heavy rain 24 95 16 km/h 6173331 201503151300 Vancouver CA Scattered clouds 6 84 12 km/h 6173331 201503151400 Vancouver CA Haze rain 5 84 12 km/h 7284824 201503151300 Budapest HU Light rain 4 80 14 km/h 7284824 201503151400 Budapest HU Light rain 4 81 14 km/h … … … … … … … … Batch operations are quite an interesting feature of Tables, as they provide quasi-ACID transactions in the Table storage. Batch operations require all the entities included to have the same partition key or else an exception will be thrown. Batch operations can perform inserts, updates, and deletes in the same operation, and can include up to 100 entities with a payload size of 4 MB only. Updating entities In order to update an entity, we need to retrieve it first, then modify its properties to save it back again. TableOperation supports two types of updates: Replace and Merge. If the entity was modified between the retrieval and saving, an error will be generated and the execution of the operation will fail. The Replace method will replace the values of the properties of an existing item with the object we provide. Have a look at the following code that changes an existing record for Seattle city for a specific day and hour: TableOperation retrieveOperation = TableOperation.Retrieve<WeatherEntity> ("5809844", "201503151300"); TableResult result = table.Execute(retrieveOperation); WeatherEntity updateEntity = (WeatherEntity)result.Result; if(updateEntity != null) { updateEntity.Temperature = 26; TableOperation updateOperation = TableOperation.Merge(updateEntity); table.Execute(updateOperation); } Notice in the preceding code that the TableOperation.Retrieve method takes the partition key with the row key as arguments, and retrieves the entity into a TableResult object that contains the Result property that can be casted into a WeatherEntity object. But that's not all, changing an existing property in an entity is not the only type of update that may be required. As we have discussed previously, tables are schema-less, allowing entities in the same table to have different properties, which also means that you can add or remove columns even after the creation of a record. Suppose you want to add more properties to a weather record, you can achieve this by modifying the class WeatherEntity and adding the new properties to it. But what if you don't want to change the class since it's a rare collection of data that you are adding? This is where Merge steps in: it allows you to merge changes with an existing entity without overwriting old data. TableOperation retrieveOperation = TableOperation.Retrieve<WeatherEntity> ("5809844", "201503151300"); //all records for Seattle at March 15, 2015 TableResult result = table.Execute(retrieveOperation); WeatherEntity originalEntity =(WeatherEntity)result.Result; if (originalEntity != null) { DynamicTableEntity dynamicEntity = new DynamicTableEntity() { PartitionKey = originalEntity .PartitionKey, RowKey = originalEntity .RowKey, ETag = originalEntity .ETag, Properties = new Dictionary<string, EntityProperty> { {"Visibility", new EntityProperty("16093")}, {"Pressure", new EntityProperty("1015")} } }; TableResult results = table.Execute(TableOperation.Merge(dynamicEntity )); } The preceding code gets an existing weather entity and assigns it to the originalEntity, object. Then it creates a new object, DynamicTableEntity and copies the PartitionKey, RowKey, and ETag to the new object and adds two properties, Language and Country, as defined previously. TableOperation.Merge was executed over the newly created object. What this code does is that it adds two properties to the weather record without changing other existing properties. If we had used Replace instead, the original WeatherEntity properties CityName, CountryCode, Description, Temperature, Humidity, and Wind would have lost their values. Copying the three properties PartitionKey, RowKey, and ETag (for optimistic concurrency) to the newly created DynamicTableEntity is mandatory and without it the operation would have failed. Our Weather table now looks like this: PartitionKey RowKey City Country Description   Humidity Wind Visibility Pressure …. … … … … … … …     5128638 201503151400 New York US Few clouds 25 46 11 km/h     5809844 201503151300 Seattle US Light rain 23 82 16 km/h 16093 1015 5809844 201503151400 Seattle US Heavy rain 24 95 16 km/h     6173331 201503151300 Vancouver CA Scattered clouds 6 84 12 km/h     … … … … … … … …     As mentioned earlier, operations will fail if the entity has changed between the retrieval and the update. Sometimes you are not sure if the object already exists on the server or not. You might need to overwrite or insert your values regardless; to do that you can use the InsertOrReplace operation. This will overwrite your values even if they were changed, and if the record doesn't exist it will be inserted. Deleting an entity can be achieved after retrieving it, as follows: TableOperation deleteOperation = TableOperation.Delete(originalEntity); Summary In this article we have discussed the basics of Table storage, which is the key/value NoSQL storage option offered by Azure platform. We have performed basic operations on entities and tables. Resources for Article: Further resources on this subject: Windows Azure Service Bus: Key Features[article] Digging into Windows Azure Diagnostics[article] Windows Azure Diagnostics: Initializing the Configuration and Using a Configuration File [article]
Read more
  • 0
  • 0
  • 11576

article-image-user-interface
Packt
23 Sep 2015
10 min read
Save for later

User Interface

Packt
23 Sep 2015
10 min read
This article, written by John Doran, the author of the Unreal Engine Game Development Cookbook, covers the following recipes: Creating a main menu Animating a menu (For more resources related to this topic, see here.) In order to create a good game project, you need to be able to communicate information to the player. To do this, we need to create a user interface (UI), which will allow us to display information such as the player's health, inventory, and so on. Inside Unreal 4, we use the Slate UI framework to create user interfaces, however, it's a very complex system. To make things easier for end users, Unreal also released the Unreal Motion Graphics (UMG) UI Designer which is a visual UI authoring tool with a much easier workflow. This is what we will be using in this article. For more information on Slate, refer to https://docs.unrealengine.com/latest/INT/Programming/Slate/index.html. Creating a main menu A main menu can serve as an introduction to your game and is a great place for us to discuss some additional things that UMG has, such as Texts and Buttons. We'll also learn how we can make buttons do things. Let's spend some time to see just how easy it is to create one! For more information on the client-server model, refer to https://en.wikipedia.org/wiki/Client%E2%80%93server_model. How to do it… To give you an idea of how it works, let's take a simple example of a coin collectable: Create a new level by going to File | New Level and select Empty Level. Next, inside the Content Browser tab, go to our UI folder, then to Add New | User Interface | Widget Blueprint, and give it a name of MainMenu. Double-click on it to open the editor. In this menu, we are going to have the title of the game and then a series of buttons the player can press: From the Palette tab, open up the Common section and drag and drop a Button onto the middle of the screen. Select the button and change its Size X to 400 and Size Y to 80. We will also rename the button to Play Game. Drag and drop a Text object onto the Play Game button and you should see it snap on to the button as a child. Under Content, change Text to Play Game. From here under Appearance, change the color of the button to black and change the Font size to 32. From the Hierarchy tab, select the Play Game button and copy and paste it to create duplicate. Move the button down, rename it to Quit Game, and change the Text to Content as well. Move both of the objects so that they're on the bottom part of the HUD, slightly above and side by side, as shown in the following image: Lastly, we'll want to set our pivots and anchors accordingly. When you select either the Quit Game or Play Game buttons, you may notice a sun-like looking widget that displays the Anchors of the object (known as the Anchor Medallion). In our case, open Anchors from the Details panel and click on the bottom-center option. Now that we have the buttons created, we want them to actually do something when we click on them. Select the Play Game button and from the Details tab, scroll down until you see the Events component. There should be a series of big green + buttons. Click on the green button beside OnClicked. Next, it will take us to the Event Graph with the appropriate event created for us. To the right of the event, right-click and create an Open Level action. Under Level Name, put in whatever level you like (for example, StarterMap) and then connect the output of the OnClicked action to the input of the Open Level action. To the right of that, create a Remove from Parent action to make sure that when we leave that, the menu doesn't stay. Finally, create a Get Player Controller action and to the right of it a Set Show Mouse Cursor action, which should be disabled, so that the mouse will no longer be visible since we will want to see the mouse in the menu. (Drag Return Value from the Get Player Controller action to create a new node and search for the mouse cursor action.) Now, go back to the Designer button and then select the Quit Game button. Click on the OnClicked button as well and to the right of this one, create a Quit Game action and connect the output of the OnClicked action to the input of the Quit Game action. Lastly, as a bit of polish, let's add our game's title to the screen. Drag and drop another Text object onto the scene, this time with Anchor at the top-center. From here, change Position X to 0 and Position Y to 176. Change Alignment in the X axis to .5 and check the Size to Content option for it to automatically resize. Set the Content component's Text property to the game's name (in my case, Game Name). Under the Appearance component, set the Font size to 93 and set Justification to Center. There are a number of other styling options that you may wish to use when developing your HUDs. For more information about it, refer to https://docs.unrealengine.com/latest/INT/Engine/UMG/UserGuide/Styling/index.html. Compile the menu, and saveit. Now we need to actually have the widget show up. To do so, we'll need to take the same steps as we did earlier. Open up Level Blueprint by going to Blueprints | Open Level Blueprint and create an EventBeginPlay event. Then, to the right of this, right-click and create a Create Widget action. From the dropdown under Class, select MainMenu and connect the arrow from Event Begin Play to the input of Create MainMenu_C Widget. After this, click and drag the output arrow and create an Add to Viewport event. Then, connect Return Value of our Create Widget action to Target of the Add to Viewport action. Now lastly, we also want to display the player's cursor on the screen to show buttons. To do this, right-click and select Get Player Controller. Then, from Return Value of that, create a Show Mouse Cursor object in Set. Connect the output of the Add to Viewport action to the input of the Show Mouse Cursor action. Compile, save, and run the project! With this, our menu is completed! We can quit the game without any problem, and pressing the Play Game button will start our level! Animating a menu You may have created a menu or UI element at some point, but rather than having it static and non-moving, let's spend some time looking at how we can animate the menus by having them fly in and out or animating them in some way. This will help add to the polish of the title as well as enable players to notice things easier as they move in. Getting ready Before we start working on this, we need to have a project created and set up. Do the previous recipe all the way to completion. How to do it… Open up the MainMenu blueprint once more and from the bottom-left in the Animations tab, click on the +Animation button and give the new animation a name of MenuFlyIn. Select the newly created animation and you should see the window on the right-hand side brighten up. Next, click on the Auto Key toggle to have the animation editor automatically set keys that are appropriate for our implementation. If it's not there already, move the timeline bar (the white line with two orange ends on the top and bottom) to the 0.00 mark on the animation timeline. Next, select the Game Name object and under Color and Opacity, open it and change the A (alpha) value to 0. Now move the timeline bar to the 1.00 mark and then open the color again and set the A value to 1. You'll notice a transition—going from a completely transparent text to a fully shown one. This is a good start. Let's have the buttons fly in after the text appears. Next, move the Time bar to the 2.00 mark and select the Play Game button. Now from the Details tab, you'll notice that under the variables, there are new + icons to the left of variables. This value will save the value for use in the animations. Click on the + icon by the Position Y value. If you use your scroll wheel while inside the dark grey portion of the timeline bar (where the keyframe numbers are displayed), it zooms in and out. This can be quite useful when you create more complex animations. Now move the Time bar to the 1.00 mark and move the Play Game button off the screen. By doing the animation in this way, we are saving where we want it to be first at the end, and then going back in time to do the animations. Do the same animation for the Quit Game button. Now that our animation is created, let's make it in a way so that when the object starts, this animation is played. Click on the Graph button and from the MyBlueprint tab under the Graphs section, double-click on the Event Construct event, which is called as soon as we add the menu to the scene. Grab the pin on the end of it and create a Play Animation action. Drag and drop a MenuFlyIn animation into the scene and select Get. Connect its output pin to the In Animation property of the Play Animation action. Now that we have the animation work when we create the menu, let's have it play when we leave the menu. Select the Play Animation and Menu Fly In variables and copy them. Then move to the OnClicked (Play Game) action. Drag the OnClicked event over to the left and remove its original connection to the Open Level action by holding down Alt and clicking. Now paste (Ctrl + V) the new objects and connect the out pin of OnClicked (Play Game) to the input of Play Animation. Now change Play Mode to Reverse. To the right of this, create a Delay action. For the Duration variable, we want it to wait as long as the animation is, so from the Menu Fly In variable, create another pin and create a Get End Time action. Connect Return Value of Get End Time to the input of the Delay action. Connect the output of the Play Animation action to the input of the Delay action and the Completed output of the Delay action to the input of the Open Level action. Now we need to do the same for the OnClicked (Quit Game) event. Now compile, save, and run the game! Our menu is now completed and we've learned about how animation works inside UMG! For more examples of using UMG for animation, refer to https://docs.unrealengine.com/latest/INT/Engine/UMG/UserGuide/Animation/index.html. Summary This article gave you some insight on Slate and the UMG Editor to create a number of UI elements and an animated main menu to tie your whole game together. We created a main menu and also learned how to make buttons do things. We spent some time looking at how we can animate menus by having them fly in and out. Resources for Article: Further resources on this subject: The Blueprint Class[article] Adding Fog to Your Games [article] Overview of Unreal Engine 4 [article]
Read more
  • 0
  • 0
  • 11570
Modal Close icon
Modal Close icon