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-oracle-warehouse-builder-creating-time-dimension
Packt
16 Aug 2011
8 min read
Save for later

Oracle Warehouse Builder: Creating the Time Dimension

Packt
16 Aug 2011
8 min read
  Oracle Warehouse Builder 11g R2: Getting Started 2011 Extract, Transform, and Load data to build a dynamic, operational data warehouse with Oracle Warehouse Builder 11g R2 with this book and eBook Do not be confused by the use of the word Time to refer to this dimension. In this case, it does not refer to the time of day but to time in general which can span days, weeks, months, and so on. We are using it because the Warehouse Builder uses the word Time for this type of dimension to signify a time period. So when referring to a Time dimension here, we will be talking about our time period dimension that we will be using to store the date. We will give the name Date to be clear about what information it contains. Every dimension, whether time or not, has four characteristics that have to be defined in OWB: Levels Dimension Attributes Level Attributes Hierarchies The Levels are for defining the levels where aggregations will occur, or to which data can be summed. We must have at least two levels in our Time dimension. While reporting on data from our data warehouse, users will want to see totals summed up by certain time periods such as per day, per month, or per year. These become the levels. A multidimensional implementation includes metadata to enable aggregations automatically at those levels, if we use the OLAP feature. The relational implementation can make use of those levels in queries to sum the data. The Warehouse Builder has the following Levels available for the Time dimension when using the Time Dimension Wizard, which we'll discuss in a moment: Day Fiscal week Calendar week Fiscal month Calendar month Fiscal quarter Calendar quarter Fiscal year Calendar year The Dimension Attributes are individual pieces of information we're going to store in the dimension that can be found at more than one level. Each level will have an ID that identifies that level, a start and an end date for the time period represented at that level, a time span that indicates the number of days in the period, and a description of the level. Each level has Level Attributes associated with it that provide descriptive information about the value in that level. The dimension attributes found at that level and additional attributes specific to the level are included. For example, if we're talking about the Month level, we will find attributes that describe the value for the month such as the month of the year it represents, or the month in the calendar quarter. These would be numbers indicating which month of the year or which month of the quarter it is. We must also define at least one Hierarchy for our Time dimension. A hierarchy is a structure in our dimension that is composed of certain levels in order; there can be one or more hierarchies in a dimension. Calendar month, calendar quarter, and calendar year can be a hierarchy. We could view our data at each of these levels, and the next level up would simply be a summation of all the lower-level data within that period. A calendar quarter sum would be the sum of all the values in the calendar month level in that quarter, and the multidimensional implementation includes the metadata to facilitate these kinds of calculations. This is one of the strengths of a multidimensional implementation. The good news is that the Warehouse Builder contains a wizard that will do all the work for us—create our Time dimension and define the above four characteristics - just by asking us a few questions. We could use the regular dimension wizard to create a dimension to use as a time dimension and could define our own levels but in our case, it's much simpler to make use of the special Time Dimension Wizard to create it for us.   Creating a Time dimension with the Time Dimension Wizard Let's start creating our Time dimension by launching Design Center if it's not already running. In the Project Navigator window, we're going to expand the Databases node under ACME_DW_PROJECT, and then our ACME data warehouse node ACME_DWH. We will right-click on the Dimensions node, and select New to display a dialog that will show the list of options for creating a new dimension. An example of that screen is shown next since it is a new feature of this release: We'll select the Time Dimension and click OK to launch the Create Time Dimension Wizard. The New Gallery window that we just saw is actually available from the pop-up menu on any of the nodes by selecting the New... menu entry. Most of the nodes, such as tables and dimensions, also contain a New menu entry (New Table, New Dimension, and so on.) that launches right into the wizard as if the New Gallery were displayed and the first option selected. Up until now we've been able to use that default New option to create our objects. In the previous release of the Warehouse Builder, if there were multiple options for the New menu option they appeared as sub-menus. This release combines those options into a list in this New Gallery window. The Time Dimension Wizard will walk us through a six-step process to define the characteristics of our Time dimension. The first screen will describe these steps for us, which is shown here so we can see what it will be asking us: The first step of the wizard will ask us for a name for our Time dimension. We're going to call it DATE_DIM. If we try to use just DATE, it will give us an error message because that is a reserved word in the Oracle Database; so it won't let us use it. The next step will ask us what type of storage to use for our new dimension, shown as follows: Here we get to designate whether we want a relational physical implementation in the database or a multidimensional implementation. This is what was referred as checking a box to switch between the two. Simply select one or the other, and this is how our design will be implemented in the database with no changes by us required at all. New in release 11gR2 is the support for cube materialized views in the database for the ROLAP option so there are actually two ROLAP options to choose from but either one results in a relational implementation in the database. Oracle OLAP 11.1 introduced the concept of materialized views for cubes for query performance improvement and this new release of the Warehouse Builder now supports the ability to use them. See the Oracle OLAP Users Guide for more information on using cube materialized views at the following URL: http://download.oracle.com/docs/cd/E11882_01/olap.112/e17123/toc.htm. We're going to implement our data warehouse using the pure relational option and not implement any OLAP features so we're going to select ROLAP: Relational Storage, as shown in the image above and will not select the materialized view option. Both the pure relational implementation and the relational OLAP option are available by selecting the ROLAP option here. We can set a deployment configuration option that defaults to deploying data objects only. But this can be changed to deploy the OLAP metadata to the OLAP catalog also. In both cases, this will result in the generation of relational database objects in a star schema. However, if that option is selected, it will only store the OLAP metadata in the OLAP catalog in the database. We'll see where to set that option when we look at the data object editor and configuring a dimension. Now this brings us to step 3, which asks us to specify the data generation information for our dimension. The Time Dimension Wizard will be automatically creating a mapping for us to populate our Time dimension and will use this information to load data into it. It asks us what year we want to start with, and then how many total years to include starting with that year. The numbers entered here will be determined by what range of dates we expect to load the data for, which will depend on how much historical data we will have available to us. We have checked with the DBAs for ACME Toys and Gizmos Company to get an idea of how many years' worth of data they have and have found out that there is data for 2007, 2008, and 2009 available to us. Based on this information, we're going to set the start year to 2007 with the number of years set to three to bring us up to 2009. The other option available to us on the data generation step is the type of Time dimension to create. It can be based on a calendar year or fiscal year. This provides us with the flexibility to define our Time dimension based on what our company actually uses for its financial year. ACME Toys and Gizmos Company operates on a calendar-year basis, so we'll leave it set at calendar.  
Read more
  • 0
  • 0
  • 3283

article-image-creating-cube-oracle-warehouse-builder
Packt
16 Aug 2011
7 min read
Save for later

Creating a Cube in Oracle Warehouse Builder

Packt
16 Aug 2011
7 min read
Oracle Warehouse Builder 11g R2: Getting Started 2011 Extract, Transform, and Load data to build a dynamic, operational data warehouse with Oracle Warehouse Builder 11g R2 with this book and eBook Creating a cube with the wizard We will start the wizard in a similar manner to how we started up the Dimension wizard. Right-click on the Cubes node under the ACME_DWH module in the Project Navigator, select New Cube to launch the cube-creation wizard. The first screen will be the welcome screen, which will summarize the steps it will lead us through as shown in the following image of the main part of the welcome dialog box: The following are the steps in the creation process: We proceed right to the first step where we give our cube a name. As we will be primarily storing sales data, let's call our cube SALES and proceed to the next step. In this step, we will select the storage type just as we do for the dimensions. We will select ROLAP: Relational Storage to match our dimension storage option, and then move to the next step. In this step, we will choose the dimensions to include with our cube. We have defined three, and want them all included. So, we can click on the double arrow in the center to move all the dimensions and select them. If we had more dimensions defined than we were going to include with this cube, we would click on each, and click on the single right arrow (to move each of them over); or we could select multiple dimensions at one time by holding down the Ctrl key as we clicked on each dimension. Then click the single right arrow to move those selected dimensions. This step looks like the following after we've made our selections: Moving on to the last step, we will enter the measures we would like the cube to contain. When we enter QUANTITY for the first measure with precision and scale set to zeros and SALES_AMOUNT with precision 10 and scale 2 for the second one, we end up with a screen that should look similar to this with the dialog box expanded to show all the columns: Clicking on Next in step 4 will bring us to the final screen where a summary of the actions it will take are listed. Selecting Finish on this screen will close the dialog box and place the cube in the Project Navigator. The final screen looks like the following when scrolled all the way to the bottom: This dialog box works in a slightly different way than the dimension wizard. This final screen is the second-to-last screen when creating a dimension. The dimension wizard will present us with the progress screen as the final step. For cubes, the process is not quite as involved. That's because at this point, the cube is basically done with nothing left to do afterwards. So we may think we missed a step, but not to worry. Clicking on Next on this screen will exit the dialog box, and the cube will be created and will be accessible in the Project Navigator window. Just as with the dimension wizard, we get to see what the cube wizard is going to create for us in the Warehouse Builder. We gave it a name, selected the dimensions to include, and specified the measures. The rest of the information was included by the wizard on its own. The wizard shows us that it will be creating a table named SALES for us that will contain the referenced columns, which it figured out from the dimension and measures information we provided. At this point, nothing has actually been created in the database apart from the definitions of the objects in the Warehouse Builder workspace. We can verify that if we look under the Tables entry under our ACME_DWH database node. We'll see a table named SALES along with tables named PRODUCT, STORE, and DATE_DIM. These are the tables corresponding to our three dimensions and the cube. You may have a slightly different table name. The wizard will not create a table with the same name as one already created, so it will append a unique number to the end to keep the table names from conflicting. This could happen if you've previously created a dimension with the same name, and then removed it and recreated it. It may not remove the associated table when you delete a cube or dimension object. The tables will appear in the Project Navigator under the Tables node. Expand that and you'll see the list of tables. Right-click a table and select Delete. The Warehouse Builder will ask if you really want to delete it, and will provide a checkbox to put the object in the recycle bin. Leave it checked just to be safe and click on OK, and the table will be removed. The foreign keys we can see in the previous image are the pointers to the dimension tables. They will make the connection between our cube and our dimensions when they are deployed to the database. When we view the region amounts, they will automatically be summed up from the amounts of the various stores in the region without us having to do anything extra. This is a nice feature the multidimensional implementation gives us, but aggregations are not created for the pure relational storage option. As we can generate either a relational or a multidimensional implementation, this had to be specified anyway and so it defaulted to sum. If we install the OLAP option or use a separate OLAP database in the future, we can change that aggregation method. But for now, we do not need it. It is possible to use aggregations with a pure relational implementation by creating separate summing tables, and there are OLAP data mining applications that can make use of them for more advanced implementations. We click on the Finish button on this final screen and our sales cube is created. We'll save our work with the Ctrl+S key combination or from the design main menu. Our cube and dimensions are now complete. Let's take a look next at data object editors where we can view and edit our objects.   Using the data object editors The object editors are the manual editor interfaces that the Warehouse Builder provides for us to create and edit objects. We did not have to use one to create a dimension, but more advanced implementations would definitely need to make use of it; for instance, to edit the cube to change the aggregation method that we just discussed. We can get to a data object editor from the Project Navigator by double-clicking on an object, or by highlighting an object (by selecting it with a single click), and then right clicking and selecting Open from the menu. Editors in this latest release are now integrated into the main Design Center interface instead of popping open in a separate window. When editing any object now, a window appears in the Design Center containing the details to edit for the object. Let's open the DATE_DIM dimension and examine the overall interface as shown here: (Move the mouse over the image to enlarge.) Your screen may look differently depending on what windows are open. The previous image depicts the Navigator window on the left which is displaying the Project Navigator, the main Editor window in the middle displaying the DATE_DIM dimension we just opened and the Property Inspector window on the right displaying properties for the DATE_DIM dimension. Any of these windows can be opened, closed, minimized, or relocated offering tremendous flexibility in laying out our working area. If a window is taking up space and we don't need it at the moment, just minimize it by clicking the minimize icon in the upper right corner of the window if that option is available. We can also close any window we want by hovering the mouse over the window title and clicking the X that appears or by right clicking over the window title and selecting Close from the popup. The main Editor window cannot be minimized but can be closed.  
Read more
  • 0
  • 0
  • 3185

article-image-creating-dimensions-oracle-warehouse-builder
Packt
16 Aug 2011
10 min read
Save for later

Creating Dimensions in Oracle Warehouse Builder

Packt
16 Aug 2011
10 min read
Oracle Warehouse Builder 11g R2: Getting Started 2011 Extract, Transform, and Load data to build a dynamic, operational data warehouse with Oracle Warehouse Builder 11g R2 with this book and eBook The Product dimension In the Product dimension, we will create the attributes that describe the products sold by ACME Toys and Gizmos. The principles of the Time dimension apply to this dimension as well. The same four characteristics need to be defined—Levels, Dimension Attributes, Level Attributes, and Hierarchies. The only difference will be that they are product-oriented instead of time/date-oriented. Let's begin by looking at the attributes of our products, and then we'll group by levels and a hierarchy. The first thing we should consider is how each toy or gizmo sold by ACME is represented. As with any retail operation, a Stock Keeping Unit (SKU) is maintained that uniquely identifies each individual type of item sold. This is an individual number assigned by the main office that uniquely identifies each type of product sold by ACME, and there could be tens of thousands of different items. There could be more than one product with the same name, but they won't have the same SKU. So the SKU, together with the NAME, forms the business identifier we can use for the products. A business identifier contains one or more attributes that have been selected by us to uniquely represent a record to differentiate it from another. These attributes are what we think of when we think about what differentiates an individual product from another. An SKU number all by itself is not very helpful. Therefore, in our Product dimension, we will want to make available more descriptive information about each product such as the description. Every SKU can be grouped together by brand name—the toy manufacturer who makes the product—and then by the category of product, such as game, doll, action figure, sporting goods, and so on. Each category could be grouped by department in the store. Already, a list of attributes is starting to take shape and a product hierarchy is forming in our minds. For each of those levels in the hierarchy, that is the department, category, and brand, we need to have a business identifier. For that the NAME will be sufficient as there are no departments, categories, or brands that have the same name. Product attributes (attribute type) ID (Dimension/Level) SKU (Level) Name (Dimension/Level) Description (Dimension/Level) List Price (Level) Product levels Department located in Category of item Brand Item Product hierarchy (highest to lowest) Department Category Brand Item Looking at the product attributes, we see that they have been listed above with the type and that ID, Name, and Description are labeled as dimension attributes. This means they can appear on more than one level. Each level has a name (Item, Brand, Category, and Department) that identifies the level, but what about the names of the individual brands, or the different categories or departments? There has to be a place to store those names and descriptions, and that is the purpose of these dimension attributes. By labeling them as dimension attributes, they appear once for each level in the dimension. They are used to store the individual names and descriptions of the brands, categories, and departments. Likewise, each level will have a unique ID that will act as the surrogate key for that level, as well as one or more attributes defined as the business identifier. In our previous discussion about the Time dimension, we saw how a surrogate key was used as an identifier and how business identifiers were used; that same principle applies here, including the use of a surrogate key which wasn't used for a time dimension. As we want the computer to do most of the work for us, let's use the OWB Dimension Wizard to create our Product dimension now that we've determined what will be in it. Creating the Product dimension with the new Dimension Wizard OWB provides a wizard that we can use to create a dimension. It is similar to the Time Dimension Wizard, but is more generic for applying to other dimensions. As a result, there will be more steps involved in the wizard, just because it has to ask us more because it will not be able to make as many assumptions as it did with the Time dimension. This wizard can be used with any dimension, and therefore things such as attributes, levels, and hierarchies are going to need to be defined explicitly. Right-click on the Dimensions node under our ACME_DWH Oracle module, which is under Databases in the Design Center Project Navigator. Choose New Dimension to launch the Create Dimension Wizard. The very first screen we'll see is the Welcome screen that will describe for us the steps that we will be going through. We can see that it requires more steps than the Time Dimension Wizard: We will have to provide a name for our dimension, and tell it what type of storage to use—relational or multidimensional—just as we did for the Time Dimension Wizard. It will then ask us to define our dimension attributes. We didn't have to do that for the Time dimension. That wizard had a preset number of attributes it defined for us automatically because it knew it was creating a Time dimension. We then had to define the levels where we simply chose from a preset list of levels for the Time dimension. Here we have to explicitly name the levels. This is where we'll have to pay close attention to aggregations. We will then choose our level attributes from the dimension attributes. Then we see in the previous figure that we will have to choose the slowly changing dimension type, which is how we want to handle changes to values in our dimension attributes over time. This is a new concept we haven't dealt with yet that pertains to dimensional modeling, and we'll soon briefly discuss just what that involves when we see the choices we'll be able to make for it. We'll then get a last chance to review the settings, and then it will create the dimension for us showing us the progress, which is similar to the last two steps of the Time Dimension Wizard. After reviewing the steps, the wizard will go to the next screen where we enter a name for the dimension that we will call Product. We'll then proceed to step 2, which is where we will select the ROLAP: Relational storage option for relational, as we did for the Time dimension. Proceeding to step 3, we will be able to list the attributes that we want contained in our Product dimension. We see that the wizard was nice enough to create three attributes for us already—an ID, a NAME, and a DESCRIPTION as shown here: Notice that the wizard has already labeled the ID as the Surrogate Identifier and the Name as the Business Identifier, and selected data types for those attributes for us. If we scroll that window to the right, we'll see that it has chosen sizes for the character attributes also. We can change all of these options at this point, so let's modify and add to this list to suit our Product dimension. We'll make the following changes: Enter SKU in the name column on line 4 and leave the data type as VARCHAR2, but change the length to 50. Scroll the window to the right if any columns are not visible that need to be changed. We can also expand the dialog box to show additional columns. Enter LIST_PRICE in the name column on line 5, leave the data type as NUMBER, and leave the precision and scale as eight and two as it suggested. Make SKU a Business Identifier field in addition to Name. (Click on the drop-down box in the identifier column for SKU, and select Business.) Change the length of the NAME column from 25 to 50. Change the length of the DESCRIPTION column from 40 to 200. Notice how the precision and scale were entered automatically for us by the Wizard when we entered names for our attributes. Moreover, they tended to make sense for the type of attribute. The LIST_PRICE had a default of eight for precision and two for the scale that we did not have to modify. If we choose logical names for our measures, it is able to make very good guesses as to what the precision and scale should be. SKU is a character field created with a varchar2 type with a reasonable length. Likewise, a LIST_PRICE amount implies money which requires a number having two decimal places (scale 2). Suppose we make a mistake and enter a value and then decide not to keep it. Then we can delete the row by right-clicking on the row number to the left of the row, and then selecting Delete from the pop-up menu. The screen should now look like the following, expanded slightly to the right to see the additional length, precision, and scale columns: (Move the mouse over the image to enlarge.) If we were to scroll that window all the way to the right, or expand it completely, we'd see even more columns such as the Seconds Precision and Descriptor column. If we press the Help button, it will explain what each column is. Briefly, the Seconds Precision is applicable to only TIMESTAMP data types, and expresses the precision of the seconds' portion of the value. The Descriptor is applicable to MOLAP (multidimensional) implementations and provides six standard descriptions that can be assigned to columns. It presets two columns, the Long description and the Short description. We can safely ignore them for our application. The next step is where we can specify the levels in our dimension. There must be at least one level identified, but we are going to have four in our Product dimension. They are to be entered on this screen in order from top to bottom with the highest level listed first, then down to the lowest level. For our dimension, we'll enter DEPARTMENT, CATEGORY, BRAND, and ITEM in that order from top to bottom. You might have noticed there is no step where we get to input hierarchies. The wizard will automatically create a default hierarchy called Standard that will contain the levels we enter here in this order. To create additional hierarchies, we must use the data object editor for dimensions after creating the dimension in the wizard. The dialog box should now look like this: Moving on to the next screen, we get to specify the level attributes. At the top are the levels, and at the bottom is the list of attributes with checkboxes beside each. If we click on each level in the top portion of the dialog box, we can see in the bottom portion that the wizard has preselected attributes for us. It chooses the three default attributes it created for us to be level attributes for each level, and the other two attributes—the SKU and LIST_PRICE—that we entered as level attributes for the bottom-most level—the ITEM level. We are not going to make any changes on this screen. The wizard has chosen wisely in this case. We could edit the descriptions of each of the level attributes if we wanted to.  
Read more
  • 0
  • 0
  • 2535

article-image-magento-14-theming-working-existing-themes
Packt
16 Aug 2011
5 min read
Save for later

Magento 1.4 Theming: Working with Existing Themes

Packt
16 Aug 2011
5 min read
  Magento 1.4 Theming Cookbook Over 40 recipes to create a fully functional, feature rich, customized Magento theme         Read more about this book       (For more resources on this subject, see here.) Introduction As we have just noted, this article is going to be more practical. We are going to see some basic things that will help us modify the appearance of our site, from looking for free templates to the process of installing them and making some tiny changes. I am sure this article helps us establish a good foundation though most of the things we are going to see are quite simple, so this is going to be a good introduction. Installing a theme through Magento Connect We are going to see two ways in which we can install a new Magento theme. The first one is through Magento Connect. This involves a number of steps that we are going to follow along this recipe. Getting ready First we need to go to Magento Connect: http://www.magentocommerce.com/magentoconnect. There, search for the theme Magento Classic Theme Free, or, alternatively, load this link: http://www.magentocommerce.com/magento-connect/TemplatesMaster/extension/928/magento-classic-theme. How to do it... This theme, the Magento Classic Theme, is the one we are going to use through this article. Follow these steps to install it: First we need to log into our www.magentocommerce.com site account. This is a necessary step to get the Extension Key. The extension key can be found in a box that looks like the following screenshot: We also find some other useful info there, like the compatibility version, and the price, free in this case. There's also a button that says Get Extension Key. Click on that button: After clicking on the Get Extension Key button, the box that we can see in the preceding screenshot appears. On that image we must accept the license agreement, select the Magento version we are using, and again click on Get Extension Key: This is the last screen. We need to obtain the extension key and copy it as we are going to use it very soon. For the next steps we need to go to our Magento installation Admin area screen. There, carry out the following instructions: Go to System menu, then Magento Connect and finally Magento Connect Manager. The Magento Connect Manager screen will appear, just like the following screenshot: Here we need to insert the same login info as we used in our Magento Admin screen. In the next screen we need to insert the key we have just copied: When we click on the install button the installation process starts. It will only take a few seconds and the theme will be installed into our site. Fast and easy! How it works... We have just selected a theme from the Magento site, and installed it into our own Magento installation through the Magento Connect Manager. We can do this as many times as we want, and install as many themes as we need to. Installing a theme manually In this recipe we are going to see another method of installing themes into our Magento installation. This time we are going to see how to install a theme manually. Why is this important? Just because we may want to use themes that are not available through Magento Connect, as they can be themes purchased in other places, or downloaded from free themes. Getting ready In order to follow this method we need a downloaded theme. You can get the Magento Classic theme from this link: http://blog.templates-master.com/free-magento-classic-theme/ Once done, we will get a file called f002.classic_1.zip; just unzip it. Inside we will find many folders: graphic source: This folder has all the PSD files necessary to help us modify the theme installation: This folder is where we can find installation instructions template source 1.3.2: The theme is for Magento version 1.3.2 template source 1.4.0.1: This theme is for Magento 1.4.0.1 template source 1.4.1.0: This theme is for Magento 1.4.1.0 Though our Magento version is not 1.4.1.0, we could use the theme without problems. What can we find inside that folder? Another two folders: app skin This is the folder structure we should expect from a Magento theme. How to do it... Installing a theme is as easy as copying those two folders into our Magento installation, with all their sub folders and files. In our Magento installation you will see another app and skin folder, so the contents in the folder of the downloaded theme will combine with the already existing ones. No overwriting should occur. And that's all; we don't need to do anything else. Selecting the recently installed theme Good, now we have installed one theme, one way or the other. So, how do we enable this theme? In fact it's quite easy; we can achieve just that from our site admin panel. Getting ready If you haven't logged into your Magento installation, do it now. How to do it... Well, once we are inside the admin panel of our site, we need to carry out the following steps to select our new theme: Go to System menu, and then click on Configuration. Look at the General block and select Design. There you will see the following screenshot: There, in Current Package Name, we can leave it as default. In the Themes section, in the Default column, we can enter the name of the theme, f002 for this example. We are done. Click on the Save config button and refresh the frontend. You will be able to see the changes. How it works... We are done. We have just selected the new theme. As promised it was quite easy, wasn't it? Try it yourself!
Read more
  • 0
  • 0
  • 1947

article-image-overview-node-package-manager
Packt
11 Aug 2011
5 min read
Save for later

An Overview of the Node Package Manager

Packt
11 Aug 2011
5 min read
Node Web Development npm package format An npm package is a directory structure with a package.json file describing the package. This is exactly what we just referred to as a Complex Module, except npm recognizes many more package.json tags than does Node. The starting point for npm's package.json is the CommonJS Packages/1.0 specification. The documentation for npm's package.json implementation is accessed with the following command: $ npm help json A basic package.json file is as follows: { name: "packageName", version: "1.0", main: "mainModuleName", modules: { "mod1": "lib/mod1", "mod2": "lib/mod2" } } The file is in JSON format which, as a JavaScript programmer, you should already have seen a few hundred times. The most important tags are name and version. The name will appear in URLs and command names, so choose one that's safe for both. If you desire to publish a package in the public npm repository it's helpful to check and see if a particular name is already being used, at http://search.npmjs.org or with the following command: $ npm search packageName The main tag is treated the same as complex modules. It references the module that will be returned when invoking require('packageName'). Packages can contain many modules within themselves, and those can be listed in the modules list. Packages can be bundled as tar-gzip tarballs, especially to send them over the Internet. A package can declare dependencies on other packages. That way npm can automatically install other modules required by the module being installed. Dependencies are declared as follows: "dependencies": { "foo" : "1.0.0 - 2.9999.9999" , "bar" : ">=1.0.2 <2.1.2" } The description and keywords fields help people to find the package when searching in an npm repository (http://search.npmjs.org). Ownership of a package can be documented in the homepage, author, or contributors fields: "description": "My wonderful packages walks dogs", "homepage": "http://npm.dogs.org/dogwalker/", "author": dogwhisperer@dogs.org Some npm packages provide executable programs meant to be in the user's PATH. These are declared using the bin tag. It's a map of command names to the script which implements that command. The command scripts are installed into the directory containing the node executable using the name given. bin: { 'nodeload.js': './nodeload.js', 'nl.js': './nl.js' }, The directories tag documents the package directory structure. The lib directory is automatically scanned for modules to load. There are other directory tags for binaries, manuals, and documentation. directories: { lib: './lib', bin: './bin' }, The script tags are script commands run at various events in the lifecycle of the package. These events include install, activate, uninstall, update, and more. For more information about script commands, use the following command: $ npm help scripts This was only a taste of the npm package format; see the documentation (npm help json) for more. Finding npm packages By default npm modules are retrieved over the Internet from the public package registry maintained on http://npmjs.org. If you know the module name it can be installed simply by typing the following: $ npm install moduleName But what if you don't know the module name? How do you discover the interesting modules? The website http://npmjs.org publishes an index of the modules in that registry, and the http://search.npmjs.org site lets you search that index. npm also has a command-line search function to consult the same index: $ npm search mp3 mediatags Tools extracting for media meta-data tags =coolaj86 util m4a aac mp3 id3 jpeg exiv xmp node3p An Amazon MP3 downloader for NodeJS. =ncb000gt Of course upon finding a module it's installed as follows: $ npm install mediatags After installing a module one may want to see the documentation, which would be on the module's website. The homepage tag in the package.json lists that URL. The easiest way to look at the package.json file is with the npm view command, as follows: $ npm view zombie ... { name: 'zombie', description: 'Insanely fast, full-stack, headless browser testing using Node.js', ... version: '0.9.4', homepage: 'http://zombie.labnotes.org/', ... npm ok You can use npm view to extract any tag from package.json, like the following which lets you view just the homepage tag: $ npm view zombie homepage http://zombie.labnotes.org/ Using the npm commands The main npm command has a long list of sub-commands for specific package management operations. These cover every aspect of the lifecycle of publishing packages (as a package author), and downloading, using, or removing packages (as an npm consumer). Getting help with npm Perhaps the most important thing is to learn where to turn to get help. The main help is delivered along with the npm command accessed as follows: For most of the commands you can access the help text for that command by typing the following: $ npm help <command> The npm website (http://npmjs.org/) has a FAQ that is also delivered with the npm software. Perhaps the most important question (and answer) is: Why does npm hate me? npm is not capable of hatred. It loves everyone, even you.  
Read more
  • 0
  • 0
  • 2629

article-image-digging-windows-azure-diagnostics
Packt
11 Aug 2011
14 min read
Save for later

Digging into Windows Azure Diagnostics

Packt
11 Aug 2011
14 min read
Diagnostic data can be used to identify problems with a hosted service. The ability to view the data from several sources and across different instances eases the task of identifying a problem. Diagnostic data can be used to identify when service capacity is either too high or too low for the expected workload. This can guide capacity decisions such as whether to scale up or down the number of instances. The configuration of Windows Azure Diagnostics is performed at the instance level. The code to do that configuration is at the role level, but the diagnostics configuration for each instance is stored in individual blobs in a container named wad-control-container located in the storage service account configured for Windows Azure Diagnostics. Read more: Windows Azure Diagnostics: Initializing the Configuration and Using a Configuration File There is no need for application data and diagnostics data to be located in the same storage service account. Indeed, a best practice from both security and performance perspectives would be to host application data and diagnostic data in separate storage service accounts. The configuration of Windows Azure Diagnostics is centered on the concept of data buffers with each data buffer representing a specific type of diagnostic information. Some of the data buffers have associated data sources which represent a further refining of the data captured and persisted. For example, the performance counter data buffer has individual data sources for each configured performance counter. Windows Azure Diagnostics supports record-based data buffers that are persisted to Windows Azure tables and file-based data buffers that are persisted to Windows Azure blobs. In the Accessing data persisted to Windows Azure Storage recipe we see that we can access the diagnostic data in the same way we access other data in Windows Azure storage. Windows Azure Diagnostics supports the following record-based data buffers: Windows Azure basic logs Performance counters Windows Event Logs Windows Azure Diagnostic infrastructure logs The Windows Azure basic logs data buffer captures information written to a Windows Azure trace listener. In the Using the Windows Azure Diagnostics trace listener recipe, we see how to configure and use the basic logs data buffer. The performance counters data buffer captures the data of any configured performance counters. The Windows Event Logs data buffer captures the events form any configured Windows Event Log. The Windows Azure Diagnostic infrastructure logs data buffer captures diagnostic data produced by the Windows Azure Diagnostics process. Windows Azure Diagnostics supports the following file-based data sources for the Directories data buffer: IIS logs IIS Failed Request Logs Crash dumps Custom directories The Directories data buffer copies new files in a specified directory to blobs in a specified container in the Windows Azure Blob Service. The data captured by IIS Logs, IIS Failed Request Logs, and crash dumps is self-evident. With the custom directories data source, Windows Azure Diagnostics supports the association of any directory on the instance with a specified container in Windows Azure storage. This allows for the coherent integration of third-party logs into Windows Azure Diagnostics. We see how to do this in the Implementing custom logging recipe. The implementation of Windows Azure Diagnostics was changed in Windows Azure SDK v1.3 and it is now one of the pluggable modules that have to be explicitly imported into a role in the service definition file. As Windows Azure Diagnostics persists both its configuration and data to Windows Azure storage, it is necessary to specify a storage service account for diagnostics in the service configuration file. The default configuration for Windows Azure Diagnostics captures some data but does not persist it. Consequently, the diagnostics configuration should be modified at role startup. In the Initializing the configuration of Windows Azure Diagnostics recipe, we see how to do this programmatically, which is the normal way to do it. In the Using a configuration file with Windows Azure Diagnostics recipe, we see how to use a configuration file to do this, which is necessary in a VM role. In normal use, diagnostics data is captured all the time and is then persisted to the storage service according to some schedule. In the event of a problem, it may be necessary to persist diagnostics data before the next scheduled transfer time. We see how to do this in the Performing an on-demand transfer recipe. Both Microsoft and Cerebrata have released PowerShell cmdlets that facilitate the remote administration of Windows Azure Diagnostics. We see how to do this in the Using the Windows Azure Platform PowerShell cmdlets to configure Windows Azure Diagnostics recipe. There are times, especially early in the development process, when non-intrusive diagnostics monitoring is not sufficient. In the Using IntelliTrace to Diagnose Problems with a Hosted Service recipe, we see the benefits of intrusive monitoring of a Windows Azure role instance. Using the Windows Azure Diagnostics trace listener Windows Azure Diagnostics supports the use of Trace to log messages. The Windows Azure SDK provides the DiagnosticMonitorTraceListener trace listener to capture the messages. The Windows Azure Diagnostics basic logs data buffer is used to configure their persistence to the Windows Azure Table Service. The trace listener must be added to the Listeners collection for the Windows Azure hosted service. This is typically done through configuration in the appropriate app.config or web.config file, but it can also be done in code. When it creates a worker or web role, the Windows Azure tooling for Visual Studio adds the DiagnosticMonitorTraceListener to the list of trace listeners specified in the Configuration section of the relevant configuration file. Methods of the System.Diagnostics.Trace class can be used to write error, warning and informational messages. When persisting the messages to the storage service, the Diagnostics Agent can filter the messages if a LogLevel filter is configured for the BasicLogsBufferConfiguration. The Compute Emulator in the development environment adds an additional trace listener, so that trace messages can be displayed in the Compute Emulator UI. In this recipe, we will learn how to trace messages using the Windows Azure trace listener. How to do it... We are going to see how to use the trace listener provided in the Windows Azure SDK to trace messages and persist them to the storage service. We do this as follows: Ensure that the DiagnosticMonitorTraceListener has been added to the appropriate configuration file: app.config for a worker role and web.config for a web role. If necessary, add the following to the Configuration section of app.config or web.config file: <system.diagnostics> <trace> <listeners> <add type="Microsoft.WindowsAzure.Diagnostics. DiagnosticMonitorTraceListener, Microsoft.WindowsAzure.Diagnostics, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" name="AzureDiagnostics"> <filter type="" /> </add> </listeners> </trace> </system.diagnostics> Use the following to write an informational message: System.Diagnostics.Trace.TraceInformation("Information"); Use the following to write a warning message: System.Diagnostics.Trace.Warning("Warning "); Use the following to write an error message: System.Diagnostics.Trace.TraceError("Error"); Ensure that the DiagnosticMonitorConfiguration.Logs property is configured with an appropriate ScheduledTransferPeriod and ScheduledTransferLogLevelFilter when DiagnosticMonitor.Start() is invoked. How it works... In steps 1 and 2, we ensure that the DiagnosticMonitorTraceListener is added to the collection of trace listeners for the web role or worker role. In steps 3 through 5, we see how to write messages to the trace listener. In step 6, we ensure that the Diagnostic Agent has been configured to persist the messages to the storage service. Note that they can also be persisted through an on-demand transfer. This configuration is described in the recipe Initializing the configuration of Windows Azure Diagnostics. There's more... The Windows Azure SDK v1.3 introduced full IIS in place of the hosted web core used previously for web roles. With full IIS, the web role entry point and IIS are hosted in separate processes. Consequently, the trace listener must be configured separately for each process. The configuration using web.config configures the trace listener for IIS, not the web role entry point. Note that Windows Azure Diagnostics needs to be configured only once in each role, even though the trace listener is configured separately in both the web role entry point and in IIS. The web role entry point runs under a process named WaIISHost.exe. Consequently, one solution is to create a special configuration file for this process named WaIISHost.exe.config and add the trace listener configuration to it. A more convenient solution is to add the DiagnosticMonitorTraceListener trace listener programmatically to the list of trace listeners for the web role entry point. The following demonstrates an overridden OnStart() method in a web role entry point modified to add the trace listener and write an informational message: public override bool OnStart() { System.Diagnostics.Trace.Listeners.Add(new Microsoft. WindowsAzure.Diagnostics.DiagnosticMonitorTraceListener()); System.Diagnostics.Trace.AutoFlush = true; System.Diagnostics.Trace.TraceInformation("Information"); return base.OnStart(); } The AutoFlush property is set to true to indicate that messages should be flushed through the trace listener as soon as they are written. Performing an on-demand transfer The Windows Azure Diagnostics configuration file specifies a schedule in which the various data buffers are persisted to the Windows Azure Storage Service. The on-demand transfer capability in Windows Azure Diagnostics allows a transfer to be requested outside this schedule. This is useful if a problem occurs with an instance and it becomes necessary to look at the captured logs before the next scheduled transfer. An on-demand transfer is requested for a specific data buffer in a specific instance. This request is inserted into the diagnostics configuration for the instance stored in a blob in wad-control-container. This is an asynchronous operation whose completion is indicated by the insertion of a message in a specified notification queue. The on-demand transfer is configured using an OnDemandTransferOptions instance that specifies the DateTime range for the transfer, a LogLevelFilter that filters the data to be transferred, and the name of the notification queue. The RoleInstanceDiagnosticeManager.BeginOnDemandTransfer() method is used to request the on-demand transfer with the configured options for the specified data buffer. Following the completion of an on-demand transfer, the request must be removed from the diagnostics configuration for the instance by using the RoleInstanceDiagnosticManager.EndOnDemandTransfer() method. The completion message in the notification queue should also be removed. The GetActiveTransfers() and CancelOnDemandTransfers() methods of the RoleInstanceDiagnosticManager class can be used to enumerate and cancel active on-demand transfers. Note that it is not possible to modify the diagnostics configuration for the instance if there is a current request for an on-demand transfer, even if the transfer has completed. Note that requesting an on-demand transfer does not require a direct connection with the hosted service. The request merely modifies the diagnostic configuration for the instance. This change is then picked up when the Diagnostic Agent on the instance next polls the diagnostic configuration for the instance. The default value for this polling interval is 1 minute. This means that a request for an on-demand transfer needs to be authenticated only against the storage service account containing the diagnostic configuration for the hosted service. In this recipe, we will learn how to request an on-demand transfer and clean up after it completes. How to do it... We are going to see how to request an on-demand transfer and clean up after it completes. We do this as follows: Use Visual Studio to create a WPF project. Add the following assembly references to the project: Microsoft.WindowsAzure.Diagnostics.dll Microsoft.WindowsAzure.ServiceRuntime.dll Microsoft.WindowsAzure.StorageClient.dll System.configuration.dll Add a class named OnDemandTransferExample to the project. Add the following using statements to the class: using Microsoft.WindowsAzure; using Microsoft.WindowsAzure.Diagnostics; using Microsoft.WindowsAzure.Diagnostics.Management; using Microsoft.WindowsAzure.ServiceRuntime; using Microsoft.WindowsAzure.StorageClient; using System.Configuration; Add the following private member to the class: String wadNotificationQueueName = "wad-transfer-queue"; Add the following method, requesting an on-demand transfer, to the class: public void RequestOnDemandTransfer( String deploymentId, String roleName, String roleInstanceId) { CloudStorageAccount cloudStorageAccount = CloudStorageAccount.Parse( ConfigurationManager.AppSettings[ "DiagnosticsConnectionString"]); OnDemandTransferOptions onDemandTransferOptions = new OnDemandTransferOptions() { From = DateTime.UtcNow.AddHours(-1), To = DateTime.UtcNow, LogLevelFilter = Microsoft.WindowsAzure.Diagnostics.LogLevel.Verbose, NotificationQueueName = wadNotificationQueueName }; RoleInstanceDiagnosticManager ridm = cloudStorageAccount.CreateRoleInstanceDiagnosticManager( deploymentId, roleName, roleInstanceId); IDictionary<DataBufferName, OnDemandTransferInfo> activeTransfers = ridm.GetActiveTransfers(); if (activeTransfers.Count == 0) { Guid onDemandTransferId = ridm.BeginOnDemandTransfer( DataBufferName.PerformanceCounters, onDemandTransferOptions); } } Add the following method, cleaning up after an on-demand transfer, to the class: public void CleanupOnDemandTransfers() { CloudStorageAccount cloudStorageAccount = CloudStorageAccount.Parse( ConfigurationManager.AppSettings[ "DiagnosticsConnectionString"]); CloudQueueClient cloudQueueClient = cloudStorageAccount.CreateCloudQueueClient(); CloudQueue cloudQueue = cloudQueueClient.GetQueueReference( wadNotificationQueueName); CloudQueueMessage cloudQueueMessage; while ((cloudQueueMessage = cloudQueue.GetMessage()) != null) { OnDemandTransferInfo onDemandTransferInfo = OnDemandTransferInfo.FromQueueMessage( cloudQueueMessage); String deploymentId = onDemandTransferInfo.DeploymentId; String roleName = onDemandTransferInfo.RoleName; String roleInstanceId = onDemandTransferInfo.RoleInstanceId; Guid requestId = onDemandTransferInfo.RequestId; RoleInstanceDiagnosticManager ridm = cloudStorageAccount.CreateRoleInstanceDiagnosticManager( deploymentId, roleName, roleInstanceId); Boolean result = ridm.EndOnDemandTransfer(requestId); cloudQueue.DeleteMessage(cloudQueueMessage); } } Add the following Grid declaration to the Window element of MainWindow.xaml: <Grid> <Label Content="DeploymentId:" Height="28" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="30,60,0,0" Name="label1" /> <Label Content="Role name:" Height="28" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="30,110,0,0" Name="label2" /> <Label Content="Instance Id:" Height="28" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="30,160,0,0" Name="label3" /> <TextBox HorizontalAlignment="Left" VerticalAlignment="Top" Margin="120,60,0,0" Name="DeploymentId" Height="23" Width="120" Text="24447326eed3475ca58d01c223efb778" /> <TextBox HorizontalAlignment="Left" VerticalAlignment="Top" Margin="120,110,0,0" Width="120" Name="RoleName" Text="WebRole1" /> <TextBox Height="23" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="120,160,0,0" Width="120" Name="InstanceId" Text="WebRole1_IN_0" /> <Button Content="Request On-Demand Transfer" Height="23" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="60,220,0,0" Width="175" Name="RequestTransfer" Click="RequestTransfer_Click" /> <Button Content="Cleanup On-Demand Transfers" Height="23" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="300,220,0,0" Width="175" Name="CleanupTransfers" Click="CleanupTransfers_Click" /> </Grid> Add the following event handler to MainWindow.xaml.cs: private void RequestTransfer_Click( object sender, RoutedEventArgs e) { String deploymentId = DeploymentId.Text; String roleName = RoleName.Text; String roleInstanceId = InstanceId.Text; OnDemandTransferExample example = new OnDemandTransferExample(); example.RequestOnDemandTransfer( deploymentId, roleName, roleInstanceId); } Add the following event handler to MainWindow.xaml.cs: private void CleanupTransfers_Click( object sender, RoutedEventArgs e) { OnDemandTransferExample example = new OnDemandTransferExample(); example.CleanupOnDemandTransfers(); } Add the following to the configuration element of app.config: <appSettings> <add key="DiagnosticsConnectionString" value="DefaultEndpointsProtocol=https;AccountName={ ACCOUNT_NAME};AccountKey={ACCESS_KEY}"/> </appSettings> How it works... We create a WPF project in step 1 and add the required assembly references in step 2. We set up the OnDemandTransferExample class in steps 3 and 4. We add a private member to hold the name of the Windows Azure Diagnostics notification queue in step 5. In step 6, we add a method requesting an on-demand transfer. We create an OnDemandTransferOptions object configuring an on-demand transfer for data captured in the last hour. We provide the name of the notification queue Windows Azure Diagnostics inserts a message indicating the completion of the transfer. We use the deployment information captured in the UI to create a RoleInstanceDiagnosticManager instance. If there are no active on-demand transfers, then we request an on-demand transfer for the performance counters data buffer. In step 7, we add a method cleaning up after an on-demand transfer. We create a CloudStorageAccount object that we use to create the CloudQueueClient object with which we access to the notification queue. We then retrieve the transfer-completion messages in the notification queue. For each transfer-completion message found, we create an OnDemandTransferInfo object describing the deploymentID, roleName, instanceId, and requestId of a completed on-demand transfer. We use the requestId to end the transfer and remove it from the diagnostics configuration for the instance allowing on-demand transfers to be requested. Finally, we remove the notification message from the notification queue. In step 8, we add the UI used to capture the deployment ID, role name, and instance ID used to request the on-demand transfer. We can get this information from the Windows Azure Portal or the Compute Emulator UI. This information is not needed for cleaning up on-demand transfers, which uses the transfer-completion messages in the notification queue. In steps 9 and 10, we add the event handlers for the Request On-Demand Transfer and Cleanup On-Demand Transfers buttons in the UI. These methods forward the requests to the methods we added in steps 6 and 7. In step 11, we add the DiagnosticsConnectionString to the app.config file. This contains the connection string used to interact with the Windows Azure Diagnostics configuration. We must replace {ACCOUNT_NAME} and {ACCESS_KEY} with the storage service account name and access key for the storage account in which the Windows Azure Diagnostics configuration is located.
Read more
  • 0
  • 0
  • 8320
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-understanding-and-developing-node-modules
Packt
11 Aug 2011
5 min read
Save for later

Understanding and Developing Node Modules

Packt
11 Aug 2011
5 min read
Node Web Development A practical introduction to Node, the exciting new server-side JavaScript web development stack What's a module? Modules are the basic building block of constructing Node applications. We have already seen modules in action; every JavaScript file we use in Node is itself a module. It's time to see what they are and how they work. The following code to pull in the fs module, gives us access to its functions: var fs = require('fs'); The require function searches for modules, and loads the module definition into the Node runtime, making its functions available. The fs object (in this case) contains the code (and data) exported by the fs module. Let's look at a brief example of this before we start diving into the details. Ponder over this module, simple.js: var count = 0; exports.next = function() { return count++; } This defines an exported function and a local variable. Now let's use it: The object returned from require('./simple') is the same object, exports, we assigned a function to inside simple.js. Each call to s.next calls the function next in simple.js, which returns (and increments) the value of the count variable, explaining why s.next returns progressively bigger numbers. The rule is that, anything (functions, objects) assigned as a field of exports is exported from the module, and objects inside the module but not assigned to exports are not visible to any code outside the module. This is an example of encapsulation. Now that we've got a taste of modules, let's take a deeper look. Node modules Node's module implementation is strongly inspired by, but not identical to, the CommonJS module specification. The differences between them might only be important if you need to share code between Node and other CommonJS systems. A quick scan of the Modules/1.1.1 spec indicates that the differences are minor, and for our purposes it's enough to just get on with the task of learning to use Node without dwelling too long on the differences. How does Node resolve require('module')? In Node, modules are stored in files, one module per file. There are several ways to specify module names, and several ways to organize the deployment of modules in the file system. It's quite flexible, especially when used with npm, the de-facto standard package manager for Node. Module identifiers and path names Generally speaking the module name is a path name, but with the file extension removed. That is, when we write require('./simple'), Node knows to add .js to the file name and load in simple.js. Modules whose file names end in .js are of course expected to be written in JavaScript. Node also supports binary code native libraries as Node modules. In this case the file name extension to use is .node. It's outside our scope to discuss implementation of a native code Node module, but this gives you enough knowledge to recognize them when you come across them. Some Node modules are not files in the file system, but are baked into the Node executable. These are the Core modules, the ones documented on nodejs.org. Their original existence is as files in the Node source tree but the build process compiles them into the binary Node executable. There are three types of module identifiers: relative, absolute, and top-level. Relative module identifiers begin with "./" or "../" and absolute identifiers begin with "/". These are identical with POSIX file system semantics with path names being relative to the file being executed. Absolute module identifiers obviously are relative to the root of the file system. Top-level module identifiers do not begin with "." , "..", or "/" and instead are simply the module name. These modules are stored in one of several directories, such as a node_modules directory, or those directories listed in the array require.paths, designated by Node to hold these modules. Local modules within your application The universe of all possible modules is split neatly into two kinds, those modules that are part of a specific application, and those modules that aren't. Hopefully the modules that aren't part of a specific application were written to serve a generalized purpose. Let's begin with implementation of modules used within your application. Typically your application will have a directory structure of module files sitting next to each other in the source control system, and then deployed to servers. These modules will know the relative path to their sibling modules within the application, and should use that knowledge to refer to each other using relative module identifiers. For example, to help us understand this, let's look at the structure of an existing Node package, the Express web application framework. It includes several modules structured in a hierarchy that the Express developers found to be useful. You can imagine creating a similar hierarchy for applications reaching a certain level of complexity, subdividing the application into chunks larger than a module but smaller than an application. Unfortunately there isn't a word to describe this, in Node, so we're left with a clumsy phrase like "subdivide into chunks larger than a module". Each subdivided chunk would be implemented as a directory with a few modules in it. In this example, the most likely relative module reference is to utils.js. Depending on the source file which wants to use utils.js it would use one of the following require statements: var utils = require('./lib/utils'); var utils = require('./utils'); var utils = require('../utils');  
Read more
  • 0
  • 0
  • 3473

article-image-windows-azure-diagnostics-initializing-configuration-and-using-configuration-file
Packt
11 Aug 2011
8 min read
Save for later

Windows Azure Diagnostics: Initializing the Configuration and Using a Configuration File

Packt
11 Aug 2011
8 min read
  Microsoft Windows Azure Development Cookbook Over 80 advanced recipes for developing scalable services with the Windows Azure platform         Read more about this book       (For more resources on this subject, see here.) The implementation of Windows Azure Diagnostics was changed in Windows Azure SDK v1.3 and it is now one of the pluggable modules that have to be explicitly imported into a role in the service definition file. As Windows Azure Diagnostics persists both its configuration and data to Windows Azure storage, it is necessary to specify a storage service account for diagnostics in the service configuration file. The configuration of Windows Azure Diagnostics is performed at the instance level. The code to do that configuration is at the role level, but the diagnostics configuration for each instance is stored in individual blobs in a container named wad-control-container located in the storage service account configured for Windows Azure Diagnostics. Initializing the configuration of Windows Azure Diagnostics The Windows Azure Diagnostics module is imported into a role by the specification of an Import element with a moduleName attribute of Diagnostics in the Imports section of the service definition file (ServiceDefinition.csdef). This further requires the specification, in the service configuration file (ServiceConfiguration.cscfg), of a Windows Azure Storage Service account that can be used to access the instance configuration for diagnostics. This configuration is stored as an XML file in a blob, named for the instance, in a container named wad-control-container in the storage service account configured for diagnostics. The Diagnostics Agent service is started automatically when a role instance starts provided the diagnostics module has been imported into the role. Note that in Windows Azure SDK versions prior to v1.3, this is not true in that the Diagnostics Agent must be explicitly started through the invocation of DiagnosticMonitor.Start(). On instance startup, the diagnostics configuration for the instance can be set as desired in the overridden RoleEntryPoint.OnStart() method. The general idea is to retrieve the default initial configuration using DiagnosticMonitor.GetDefaultInitialConfiguration() and modify it as necessary before saving it using DiagnosticMonitor.Start(). This name is something of a relic, since Windows Azure SDK v1.3 and later, the Diagnostics Agent service is started automatically. Another way to modify the diagnostics configuration for the instance is to use RoleInstanceDiagnosticManager.GetCurrentConfiguration() to retrieve the existing instance configuration from wad-control-container. This can be modified and then saved using RoleInstanceDiagnosticManager.SetCurrentConfiguration(). This method can be used both inside and outside the role instance. For example, it can be implemented remotely to request that an on-demand transfer be performed. An issue is that using this technique during instance startup violates the principal that the environment on startup is always the same, as the existing instance configuration may already have been modified. Note that it is not possible to modify the diagnostics configuration for an instance if there is a currently active on-demand transfer. In this recipe, we will learn how to initialize programmatically the configuration of Windows Azure Diagnostics. How to do it... We are going to see how to initialize the configuration for Windows Azure Diagnostics using code. We do this as follows: Use Visual Studio to create an empty cloud project. Add a web role to the project (accept the default name of WebRole1). Add the following assembly reference to the project: System.Data.Services.Client In the WebRole class, replace OnStart() with the following: public override bool OnStart(){ WadManagement wadManagement = new WadManagement(); wadManagement.InitializeConfiguration(); return base.OnStart();} In the Default.aspx file, replace the asp:Content element named BodyContent with the following: <asp:Content ID="BodyContent" runat="server" ContentPlaceHolderID="MainContent"> <div id="xmlInner"> <pre> <asp:label id="xmlLabel" runat="server"/> </pre> </div></asp:Content> Add the following using statements to the Default.aspx.cs file: using Microsoft.WindowsAzure.ServiceRuntime; In the Default.aspx.cs file, add the following private members to the _Default class: private String deploymentId = RoleEnvironment.DeploymentId;private String roleName = RoleEnvironment.CurrentRoleInstance.Role.Name;private String instanceId = RoleEnvironment.CurrentRoleInstance.Id; In the Default.aspx.cs file, replace Page_Load() with the following: protected void Page_Load(object sender, EventArgs e){ WadManagement wad = new WadManagement(); String wadConfigurationForInstance = wad.GetConfigurationBlob( deploymentId, roleName, instanceId); xmlLabel.Text = Server.HtmlEncode(wadConfigurationForInstance);} Add a class named WadManagement to the project. Add the following using statements to the WadManagement class: using Microsoft.WindowsAzure;using Microsoft.WindowsAzure.Diagnostics;using Microsoft.WindowsAzure.Diagnostics.Management;using Microsoft.WindowsAzure.ServiceRuntime;using Microsoft.WindowsAzure.StorageClient; Add the following private members to the WadManagement class: private String wadConnectionString ="Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString";private String wadControlContainerName = "wad-control-container";private CloudStorageAccount cloudStorageAccount; Add the following constructor to the WadManagement class: public WadManagement(){ cloudStorageAccount = CloudStorageAccount.Parse( RoleEnvironment.GetConfigurationSettingValue( wadConnectionString));} Add the following methods, retrieving the instance configuration blob from Windows Azure Storage, to the WadManagement class: public String GetConfigurationBlob( String deploymentId, String roleName, String instanceId){ DeploymentDiagnosticManager deploymentDiagnosticManager = new DeploymentDiagnosticManager( cloudStorageAccount, deploymentId); String wadConfigurationBlobNameForInstance = String.Format("{0}/{1}/{2}", deploymentId, roleName, instanceId); String wadConfigurationForInstance = GetWadConfigurationForInstance( wadConfigurationBlobNameForInstance); return wadConfigurationForInstance;}private String GetWadConfigurationForInstance( String wadConfigurationInstanceBlobName){ CloudBlobClient cloudBlobClient = cloudStorageAccount.CreateCloudBlobClient(); CloudBlobContainer cloudBlobContainer = cloudBlobClient.GetContainerReference( wadControlContainerName); CloudBlob cloudBlob = cloudBlobContainer.GetBlobReference( wadConfigurationInstanceBlobName); String wadConfigurationForInstance = cloudBlob.DownloadText(); return wadConfigurationForInstance;} Add the following method, initializing the configuration of Windows Azure Diagnostics, to the WadManagement class: public void InitializeConfiguration(){ String eventLog = "Application!*"; String performanceCounter = @"Processor(_Total)% Processor Time"; DiagnosticMonitorConfiguration dmc = DiagnosticMonitor.GetDefaultInitialConfiguration(); dmc.DiagnosticInfrastructureLogs.BufferQuotaInMB = 100; dmc.DiagnosticInfrastructureLogs.ScheduledTransferPeriod = TimeSpan.FromHours(1); dmc.DiagnosticInfrastructureLogs. ScheduledTransferLogLevelFilter = LogLevel.Verbose; dmc.WindowsEventLog.BufferQuotaInMB = 100; dmc.WindowsEventLog.ScheduledTransferPeriod = TimeSpan.FromHours(1); dmc.WindowsEventLog.ScheduledTransferLogLevelFilter = LogLevel.Verbose; dmc.WindowsEventLog.DataSources.Add(eventLog); dmc.Logs.BufferQuotaInMB = 100; dmc.Logs.ScheduledTransferPeriod = TimeSpan.FromHours(1); dmc.Logs.ScheduledTransferLogLevelFilter = LogLevel.Verbose; dmc.Directories.ScheduledTransferPeriod = TimeSpan.FromHours(1); PerformanceCounterConfiguration perfCounterConfiguration = new PerformanceCounterConfiguration(); perfCounterConfiguration.CounterSpecifier = performanceCounter; perfCounterConfiguration.SampleRate = System.TimeSpan.FromSeconds(10); dmc.PerformanceCounters.DataSources.Add( perfCounterConfiguration); dmc.PerformanceCounters.BufferQuotaInMB = 100; dmc.PerformanceCounters.ScheduledTransferPeriod = TimeSpan.FromHours(1); DiagnosticMonitor.Start(cloudStorageAccount, dmc);} How it works... In steps 1 and 2, we create a cloud project with a web role. We add the required assembly reference in step 3. In step 4, we modify OnStart(), so that it initializes the configuration of Windows Azure Diagnostics. In step 5, we modify the default web page, so that it displays the content of the blob storing the instance configuration for Windows Azure Diagnostics. In step 6, we add the required using statement to Default.aspx.cs. In step 7, we add some private members to store the deployment ID, the role name, and the instance ID of the current instance. In step 8, we modify the Page_Load() event handler to retrieve the blob content and display it on the default web page. In step 9, we add the WadManagement class that interacts with the Windows Azure Blob Service. In step 10, we add the required using statements. In step 11, we add some private members to contain the name of the connection string in the service configuration file, and the name of the blob container containing the instance configuration for Windows Azure Diagnostics. We also add a CloudStorageAccount instance, which we initialize in the constructor we add in step 12. We then add, in step 13, the two methods we use to retrieve the content of the blob containing the instance configuration for Windows Azure Diagnostics. In GetConfigurationBlob(), we first create the name of the blob. We then pass this into the GetWadConfigurationForInstance() method, which invokes various Windows Azure Storage Client Library methods to retrieve the content of the blob. In step 14, we add the method to initialize the configuration of Windows Azure Diagnostics for the instance. We first specify the names of the event log and performance counter we want to capture and persist. We then retrieve the default initial configuration and configure capture of the Windows Azure infrastructure logs, Windows Event Logs, basic logs, directories, and performance counters. For each of them, we specify a data buffer size of 100 MB and schedule an hourly transfer of logged data. For Windows Event Logs, we specify that the Application!* event log should be captured locally and persisted to the storage service. The event log is specified using an XPath expression allowing the events to be filtered, if desired. We can add other event logs if desired. We configure the capture and persistence of only one performance counter—the Processor(_Total)% Processor Time. We can add other performance counters if desired. Two sections at the end of this recipe provide additional details on the configuration of event logs and performance counters. We specify a transfer schedule for the directories data buffer. The Diagnostics Agent automatically inserts special directories into the configuration: crash dumps for all roles, and IIS logs and IIS failed request logs for web roles. The Diagnostics Agent does this because the actual location of the directories is not known until the instance is deployed. Note that even though we have configured a persistence schedule for crash dumps, they are not captured by default. We would need to invoke the CrashDumps.EnableCollection() method to enable the capture of crash dumps.
Read more
  • 0
  • 0
  • 11215

article-image-tuning-websphere-security
Packt
11 Aug 2011
8 min read
Save for later

Tuning WebSphere Security

Packt
11 Aug 2011
8 min read
IBM WebSphere Application Server v7.0 Security Secure your IBM WebSphere applications with Java EE and JAAS security standards using this book and eBook Tuning general security There are several general security aspects of a WebSphere environment that can be tweaked to either loosening or tightening the security level. This tweaking will have an inversely proportional effect on performance of the WebSphere system. This section briefly describes some of them. Tightening security using the administrative connector The administrative connectors are used for communication of various WAS ND7 components such as the deployment manager, node agents, application servers, and the wsadmin interface. On the one hand, by default the connector for communication between WAS ND7 components located in different physical hosts (remote connector) uses the SOAP protocol. On the other hand, the connector for communication between WAS ND7 components located on the same physical host (local connector) by default uses the IPC protocol. The recommendation for the remote connector is to use the RMI connector. The reason for doing this is because the RMI API uses stateful connections, whereas the SOAP protocol uses stateless communication. This parameter can be changed on the application servers Administration services page. In order to get to an Administration services page, one needs to follow a breadcrumb similar to: Servers | Server Types | Application servers | AppServer_ Name | Administration services. The resulting page should be similar to the one shown in the following screenshot: It is always a good idea to perform a benchmark to ensure that performance is not being significantly affected. Disabling security attribute propagation Security Attribute Propagation (SAP) is the capability of WAS ND7 to carry principal (the caller) static and dynamic security related information from one server to another in the infrastructure according to your configuration. Static security information may include data normally derived from the user registry. On the other hand, dynamic security information may include information about the principal context such as the identity, IP, and so on. If enterprise applications are not using this type of propagation, it is recommended to disable SAP in order to avoid its overhead. In SAP, security attributes would need to be serialized using Java serialization to carry out the propagation. Therefore, by disabling this feature, the serialization portion of the process is eliminated. Disabling SAP is accomplished by adding and setting to false the property com.ibm. CSI.disablePropagationCallerList. The location where this property must be defined is at the global security level. Therefore, follow the breadcrumb Security | Global security | Custom properties. On that page you need to click on the New button and you will be presented with a page similar to the one shown in the following screenshot: For additional information on Security Attributes Propagation, refer to the WAS ND7 Information Center link: http://publib.boulder.ibm.com/infocenter/wasinfo/ v7r0/topic/com.ibm.websphere.nd.doc/info/ae/ae/csec_ secattributeprop.html Using unrestricted Java Cryptographic Extensions The JCE have been part of the Java SDK since version 1.4.x. JCE, very succinctly, is the Java technology that offers a scheme and realization for encryption, key generation, and key agreement. In addition, the JCE policy files are the portion of the JCE which determines the strength of the encryption to be supported. Furthermore, due to several country laws, the JCE policy files that are included with the WAS ND7 SDK only enables to perform strong and limited cryptography in a way that can be shipped to any country in the world. For instance, the local policy file limits encryption of various methods to the values shown in the following screenshot: IBM states that there is a possibility that the restricted policy files may affect performance. Therefore, it is strongly advised to use unrestricted encryption JCE policy files. Warning: Before you replace the JCE policy libraries with their unrestricted version, it is imperative that you check your local laws regarding encryption. Should you determine that it is permissible to use unrestricted encryption, the following procedure describes how to obtain and install the Unrestricted JCE policy files. In order to download the JAR files, you must be registered with IBM. Use your company's authentication credentials when they are requested. Obtaining the Unrestricted JCE policy files The first stage in the procedure is to obtain from IBM the ZIP file unrestricted.zip that contains the Unrestricted JCE policy files. Open the URL https://www14.software.ibm.com/webapp/iwm/web/reg/ pick.do?source=jcesdk〈=en_US. Using a browser open the Unrestricted JCE files page at https:// www14.software.ibm.com/webapp/iwm/web/reg/pick. do?source=jcesdk〈=en_US. Select the libraries for version 1.4.2+. From the choices presented, select Unrestricted JCE Policy files for SDK for all newer versions. Version 1.4.2+. Click on the Continue button. Log on with your company's credentials. Provide or update information as needed. Check the I agree check box. Click on the I confirm button. Download the unrestricted.zip file. Click on the Download now link. Installing the Unrestricted JCE policy files Once the policy files have been downloaded, you can proceed to install them. Log on to the host where WAS ND7 is installed. Do this procedure for each WAS ND node (Deployment Manager host and node hosts), that is, every host in which you have installed the WAS ND7 binaries for your environment. Stop all profiles associated with the binary installation. Extract the JAR files. Create a temporary directory and in it un-archive the content of unrestricted. zip. The content is two JAR files: local_policy.jar and US_export_policy. jar Change the working directory to security Java directory. Change the working directory to <WAS_BIN_ROOT>/java/jre/lib/security Backup existing policy files. Make a copy of the files: local_policy.jar and US_export_policy.jar located in the security directory. Install the Unrestricted JCE policy files. Copy the policy files obtained in the previous subsection into the security directory. Restart the WAS ND7 environment. Tuning CSIv2 connectivity In WAS ND7, the Common Secure Interoperability Version 2 (CSIv2) is the authentication protocol used by EJBs. CSIv2 is the security protocol that undertakes the stipulations of CORBA security for interoperability authentication, delegation, and entitlements. Therefore, if your environment is using EJBs, the following tasks can improve performance without compromising security. Using Active Authentication Protocol: Set it only to CSI When an enterprise WebSphere environment is made up of WebSphere Application nodes of multiple versions, there may be a need for setting the CSIv2 authentication protocol to both, CSI and SAS (Security Authentication Service). However, in WAS ND7, the SAS has been deprecated for communicating with WAS versions 5 and newer. Therefore, it is highly recommended to set the property com.ibm.CSI. protocol to the value csiv2. When the protocol is set to CSI, WebSphere ND7 eliminates, on both server and client, a call to an interceptor for each request that a client makes. In order to configure the protocol to CSI, the file <Profile_Root_Directory>/ properties/sas.client.props must be edited by adding the line shown below: com.ibm.CSI.protocol=csiv2 Other possible values for this property are: ibm: Should be used if the clients connecting to the WAS ND7 environment are hosted in a WebSphere Application Server version 4 or earlier setup both: Should be used if the clients that communicate with the WAS ND7 environment are hosted in WebSphere Application Server installations versions 4 or earlier and versions 5 or newer In order to make the change effective, the complete WAS ND7 cell needs to be restarted. Enforcing client certificates using SSL When a WebSphere client sends secure requests to an enterprise application hosted in a WAS ND7 setup, the requestor can be authenticated either using a user ID and password combination or an SSL certificate. Since the channel is already secure, employing ID and password to validate the communication adds overhead to both client and server. Therefore, it is recommended to select the use of client SSL certificates to perform the authentication of client requests. The configuration to enforce the use of certificates for authentication can be done at the global security level or at the security domain level. The recommendation is to do it at the global security level and use this setting in all security domains. The procedure to set the use of certificates over user IDs and passwords at the global security level is as follows: Log on to the ISC (Deployment Manager). Follow the breadcrumb Security | Global security | (Authentication | RMI/IIOP security) CSIv2 inbound communications. Refer to the next screenshot to identify the link to the CSIv2 inbound communications. Enforce the use of client SSL certificates. Set the following parameters as shown in the following screenshot: Client certificate authentication (required) Transport (SSL-required) Message layer authentication (never) Note, however, that if client fails when the message layer authentication is set to never, it may need to be modified to the supported value. Ensure not to override setting in security domains. Finally, for each security domain that is defined in your WAS ND7 environment it is recommended to set the RMI/IIOP security using the global security settings, as shown in the following screenshot: However, if additional customization of the security domain RMI/IIOP is needed, ensure to set the values for CISv2 Transport Layer and CISv2 Message Layer as those shown in step three. Save the changes of configuration. Log off.
Read more
  • 0
  • 0
  • 11928

article-image-troubleshooting-websphere-security-related-issues
Packt
11 Aug 2011
8 min read
Save for later

Troubleshooting WebSphere Security-related Issues

Packt
11 Aug 2011
8 min read
  IBM WebSphere Application Server v7.0 Security Secure your IBM WebSphere applications with Java EE and JAAS security standards using this book and eBook Troubleshooting general security configuration exceptions The selected cases in this subsection concerns the situations when various aspects of configuring security are carried out and, as a result, error conditions occur. Identifying problems with the Deployment Manager—node agent communication blues Several of the problems that may take place due to either wrong or incomplete security configuration are found in the communication of the administrative layers of the WebSphere environment, i.e., between the deployment manager and the node agent(s). A couple of the most common situations are shown below, along with recommendations as to how to correct the condition. Receiving the message HMGR0149E: node agent rejected The message HMGR0149E is the result of the Deployment Manager rejecting a request to connect from the node agent. This type of error and the display of this message normally takes place when security changes in the Deployment Manager were not synchronized with the node in question. An example of log file clip where this message is found can be seen in the following screenshot: One way to fix this problem is by using the syncNode.sh command. The syntax for this command is: syncNode.sh dmgr_host [dmgr_port] [-conntype <type>] [-stopservers] [-restart] [-quiet] [-nowait] [-logfile <filename>] [-replacelog] [-trace] [-username <username>] [-password <password>] [-localusername <localusername>] [-localpassword <localpassword>] [-profileName <profile>] syncNode.sh [-help] Furthermore, a very simple procedure to correct this problem is given next: Stop the affected node agent(s). Execute, on the node agent OS host, the syncNode.sh command. Monitor the SystemOut.log file for both dmgr and nodeagent processes. Start the node agent. For additional information on messages from the high availability manager, refer to the WAS ND7 Information Center link: http://publib.boulder.ibm.com/infocenter/wasinfo/ v7r0/topic/com.ibm.websphere.messages.doc/com.ibm. ws.hamanager.nls.HAManagerMessages.html Receiving the message ADMS0005E: node agent unable to synchronize This message, ADMS0005E, is the result of the node agent attempting to synchronize configuration with the Deployment Manager. It is likely caused when changes in security-related configuration occurred and the node agent were not available. The following screenshot shows an example of this type of error. One way to solve the issue is to shut down the node agent, and then, manually execute the command syncNode.sh from the node OS host using a user ID and password that has administrative privileges on the Deployment Manager. For syntax or usage information about this command, kindly refer to the previous example. In case this action does not solve the problem, follow the next procedure: Stop the node agent(s) Using the ISC, disable global security Restart the Deployment Manager Start the node agent(s) Perform a full synchronization using the ISC Using the ISC, enable global security Synchronize changes with all nodes Stop the node agent(s) Restart the Deployment Manager to activate global security Start the node agent(s) For additional information on messages about the administrative synchronization, refer to the WAS ND7 Information Center link: http://publib.boulder.ibm.com/infocenter/wasinfo/ v7r0/topic/com.ibm.websphere.messages.doc/com.ibm. ws.management.resources.sync.html Troubleshooting runtime security exceptions To close the section on troubleshooting, this subsection presents several cases of error or exception conditions that occur due to security configuration of various WAS ND7 environment components. Such components can be all within WAS or some components could be external, for example, the IHS/WebSphere Plug-in. Troubleshooting HTTPS communication between WebSphere Plug-in and Application Server When setting up the HTTPS communication between the WebSphere Plug-in and the WebSphere Application Server there may be instances in which exceptions and errors may occur during the configuration phase. Some of the most common are listed next. Receiving the message SSL0227E: SSL handshake fails The message SSL0227E is a common one when the main IHS process is attempting to retrieve the SSL certificate indicated by the property SSLServerCert located in the httpd.conf file. What this message is stating is that the intended SSL certificate cannot be found by its label from the key ring indicated by the directive KeyFile in the same configuration file. An example of this type of message is shown in the following screenshot. In order to correct this error, there are two possibilities that can be explored. On the one hand, one needs to insure that the directive KeyFile is pointing to the correct key ring file. That is, that the key ring file actually stores the target SSL certificate to be used with this IHS server. On the other hand, there may be a typographic error in the value of the property SSLServerCert. In other words, the label that is mapped to the target SSL certificate was misspelled in the httpd.conf file. In both cases, the command gsk7capicmd can be used to list the content of the key ring file. The syntax for listing the contents of a key ring file is: <IHS_ROOT_Directory>/bin/gsk7capicmd -cert -list all -db <Path_To_ kdb_File> -pw <kdb_File_Password> For additional information on messages about handshaking issues, refer to the IHS v7 Information Center link: http://publib.boulder.ibm.com/infocenter/wasinfo/v7r0/ topic/com.ibm.websphere.ihs.doc/info/ihs/ihs/rihs_ troubhandmsg.html Receiving ws_config_parser errors while loading the plugin configuration file If the configParserParse message of the ws_config_parser component is observed in the errors log file of the IBM HTTP Server; the following screenshot is an example of a possible output that may be found in the error logs. There may be a couple of reasons for this type of message to appear in the logs. One reason for this type of message is that it occurs at the time in which the IHS process is being brought down. The WebSphere Plug-in module is in its cycle to reparse the plugin-cfg.xml file while the IHS process is shutting down, therefore the ws_config_parser component does not have enough resources to perform the parsing of the configuration file and throws this message, possibly multiple times in a row. In order to ensure that this is the correct interpretation of the message, it is necessary to find an indicator, such as a 'shutting down' type of message like the one shown in the next screenshot: The other reason why this message may appear in the logs is very likely that the process owner of the IHS process does not have the correct privileges to read the plugin-cfg.xml file. In this case, ensure that the definition for the property User in the httpd.conf file has enough privileges to read the plug-in configuration file defined for the property WebSpherePluginConfig of the httpd.conf file. For additional information on messages about WebSphere Plug-in issues, refer to the article Error message definitions for WebSphere Application Server's webserver plugin component. Receiving the message GSK_ERROR_BAD_CERT: No suitable certificate found The message GSK_ERROR_BAD_CERT appears in log files when the WebSphere Plug-in is attempting to establish an SSL connection with the back-end WebSphere Application Server and it does not have a way to validate the SSL certificate sent by the WebSphere Application Server. An example of this type of message is shown in the next screenshot: One way to solve this problem is by adding to the IHS key ring file the signer certificate from the WebSphere Application Server. When doing this, care must be taken to correctly select the WebSphere trust store. In other words, the correct scope for your target Application Server needs to be identified so that the appropriate trust store can be accessed. For instance, if it was desired to obtain the root certificate (aka, signer certificate) used by the Chap7AppServer Application Server, one needs to identify the scope for that application server. Therefore, one should start with the following breadcrumb in the ISC (Deployment Manager console): Security | SSL certificate and key management | Manage endpoint security configurations. The following screenshot illustrates a portion of the resulting page: Once the appropriate scope is identified, continue by completing the breadcrumb: Security | SSL certificate and key management | Manage endpoint security configurations | Chap7AppServer | Key stores and certificates | NodeDefaultTrustStore | Signer certificates. The following screenshot shows a portion of a resulting page. You are now in position to extract the Application Server signer SSL certificate. Once this certificate is extracted, it needs to be imported into the IHS key ring file as a root certificate.
Read more
  • 0
  • 0
  • 9271
article-image-using-intellitrace-diagnose-problems-hosted-service
Packt
11 Aug 2011
4 min read
Save for later

Using IntelliTrace to Diagnose Problems with a Hosted Service

Packt
11 Aug 2011
4 min read
  Microsoft Windows Azure Development Cookbook Over 80 advanced recipes for developing scalable services with the Windows Azure platform         Read more about this book       (For more resources on this subject, see here.) Windows Azure Diagnostics provides non-intrusive support for diagnosing problems with a Windows Azure hosted service. This non-intrusion is vital in a production service. However, when developing a hosted service, it may be worthwhile to get access to additional diagnostics information even at the cost of intruding on the service. The Visual Studio 2010 Ultimate Edition supports the use of IntelliTrace with an application deployed to the cloud. This can be particularly helpful when dealing with problems, such as missing assemblies. It also allows for the easy identification and diagnosis of exceptions. Note that IntelliTrace has a significant impact on the performance of a hosted service. Consequently, it should never be used in a production environment and, in practice, should only be used when needed during development. IntelliTrace is configured when the application package is published. This configuration includes specifying the events to trace and identifying the modules and processes for which IntelliTrace should not capture data. For example, the Storage Client module is removed by default from IntelliTrace since otherwise, storage exceptions could occur due to timeouts. Once the application package has been deployed, the Windows Azure Compute node in the Visual Studio Server Explorer indicates the Windows Azure hosted service, roles, and instances which are capturing IntelliTrace data. From the instance level in this node, a request can be made to download the current IntelliTrace log. This lists: Threads Exceptions System info Modules The threads section provides information about when particular threads were running. The exceptions list specifies the exceptions that occurred, and provides the call stack when they occurred. The system info section provides general information about the instance, such as number of processors and total memory. The modules section lists the loaded assemblies. The IntelliTrace logs will probably survive an instance crash, but they will not survive if the virtual machine is moved due to excessive failure. The instance must be running for Visual Studio to be able to download the IntelliTrace logs. In this recipe, we will learn how to use IntelliTrace to identify problems with an application deployed to a hosted service in the cloud. Getting ready Only Visual Studio Ultimate Edition supports the use of IntelliTrace with an application deployed to a hosted service in the cloud. How to do it... We are going to use IntelliTrace to investigate an application deployed to a hosted service in the cloud. We do this as follows: The first few steps occur before the application package is deployed to the cloud: Use Visual Studio 2010 Ultimate Edition to build a Windows Azure project. Right click on the Solution and select Publish.... Select Enable IntelliTrace for .Net 4 roles. Click on Settings... and make any changes desired to the IntelliTrace settings for modules excluded, and so on. Click on OK to continue the deployment of the application package. The remaining steps occur after the package has been deployed and the hosted service is in the Ready (that is, running) state: Open the Server Explorer in Visual Studio. On the Windows Azure Compute node, right click on an instance node and select View IntelliTrace logs. Investigate the downloaded logs, looking at exceptions and their call stacks, and so on. Right click on individual lines of code in a code file and select Search For This Line In IntelliTrace. Select one of the located uses and step through the code from the line. How it works... Steps 1 through 5 are a normal application package deployment except for the IntelliTrace configuration. In steps 6 and 7, we use Server Explorer to access and download the IntelliTrace logs. Note that we can refresh the logs through additional requests to View IntelliTrace logs. In steps 8 through 10, we look at various aspects of the downloaded IntelliTrace logs. Further resources on this subject: Windows Azure Diagnostics: Initializing the Configuration and Using a Configuration File [Article] Digging into Windows Azure Diagnostics [Article] Managing Azure Hosted Services with the Service Management API [Article] Autoscaling with the Windows Azure Service Management REST API [Article] Using the Windows Azure Platform PowerShell Cmdlets [Article]
Read more
  • 0
  • 0
  • 2178

article-image-glsl-40-discarding-fragments-create-perforated-look
Packt
10 Aug 2011
4 min read
Save for later

GLSL 4.0: Discarding Fragments to Create a Perforated Look

Packt
10 Aug 2011
4 min read
OpenGL 4.0 Shading Language Cookbook The result will look like the following image: Getting ready The vertex position, normal, and texture coordinates must be provided to the vertex shader from the OpenGL application. The position should be provided at location 0, the normal at location 1, and the texture coordinates at location 2. As in previous examples, the lighting parameters must be set from the OpenGL application via the appropriate uniform variables. How to do it... To create a shader program that discards fragments based on a square lattice (as in the preceding image), use the following code: Use the following code for the vertex shader: #version 400 layout (location = 0) in vec3 VertexPosition; layout (location = 1) in vec3 VertexNormal; layout (location = 2) in vec2 VertexTexCoord; out vec3 FrontColor; out vec3 BackColor; out vec2 TexCoord; struct LightInfo { vec4 Position; // Light position in eye coords. vec3 La; // Ambient light intensity vec3 Ld; // Diffuse light intensity vec3 Ls; // Specular light intensity }; uniform LightInfo Light; struct MaterialInfo { vec3 Ka; // Ambient reflectivity vec3 Kd; // Diffuse reflectivity vec3 Ks; // Specular reflectivity float Shininess; // Specular shininess factor }; uniform MaterialInfo Material; uniform mat4 ModelViewMatrix; uniform mat3 NormalMatrix; uniform mat4 ProjectionMatrix; uniform mat4 MVP; void getEyeSpace( out vec3 norm, out vec4 position ) { norm = normalize( NormalMatrix * VertexNormal); position = ModelViewMatrix * vec4(VertexPosition,1.0); } vec3 phongModel( vec4 position, vec3 norm ) { // The ADS shading calculations go here (see: "Using // functions in shaders," and "Implementing // per-vertex ambient, diffuse and specular (ADS) shading") ... } void main() { vec3 eyeNorm; vec4 eyePosition; TexCoord = VertexTexCoord; // Get the position and normal in eye space getEyeSpace(eyeNorm, eyePosition); FrontColor = phongModel( eyePosition, eyeNorm ); BackColor = phongModel( eyePosition, -eyeNorm ); gl_Position = MVP * vec4(VertexPosition,1.0); } Use the following code for the fragment shader: #version 400 in vec3 FrontColor; in vec3 BackColor; in vec2 TexCoord; layout( location = 0 ) out vec4 FragColor; void main() { const float scale = 15.0; bvec2 toDiscard = greaterThan( fract(TexCoord * scale), vec2(0.2,0.2) ); if( all(toDiscard) ) discard; if( gl_FrontFacing ) FragColor = vec4(FrontColor, 1.0); else FragColor = vec4(BackColor, 1.0); } Compile and link both shaders within the OpenGL application, and install the shader program prior to rendering. How it works... Since we will be discarding some parts of the teapot, we will be able to see through the teapot to the other side. This will cause the back sides of some polygons to become visible. Therefore, we need to compute the lighting equation appropriately for both sides of each face. We'll use the same technique presented earlier in the two-sided shading recipe. The vertex shader is essentially the same as in the two-sided shading recipe, with the main difference being the addition of the texture coordinate. The differences are highlighted in the above listing. To manage the texture coordinate, we have an additional input variable, VertexTexCoord, that corresponds to attribute location 2. The value of this input variable is passed directly on to the fragment shader unchanged via the output variable TexCoord. The ADS shading model is calculated twice, once using the given normal vector, storing the result in FrontColor, and again using the reversed normal, storing that result in BackColor. In the fragment shader, we calculate whether or not the fragment should be discarded based on a simple technique designed to produce the lattice-like pattern shown in the preceding image. We first scale the texture coordinate by the arbitrary scaling factor scale. This corresponds to the number of lattice rectangles per unit (scaled) texture coordinate. We then compute the fractional part of each component of the scaled texture coordinate using the built-in function fract. Each component is compared to 0.2 using the built-in function greaterThan, and the result is stored in the bool vector toDiscard. The greaterThan function compares the two vectors component-wise, and stores the Boolean results in the corresponding components of the return value. If both components of the vector toDiscard are true, then the fragment lies within the inside of each lattice frame, and therefore we wish to discard this fragment. We can use the built-in function all to help with this check. The function all will return true if all of the components of the parameter vector are true. If the function returns true, we execute the discard statement to reject the fragment. In the else branch, we color the fragment based on the orientation of the polygon, as in the two-sided shading recipe presented earlier. Summary This recipe showed us how to use the discard keyword to "throw away" fragments and create a perforated look. Further resources on this subject: Tips and Tricks for Getting Started with OpenGL and GLSL 4.0 [Article] OpenGL 4.0: Using Uniform Blocks and Uniform Buffer Objects [Article] OpenGL 4.0: Building a C++ Shader Program Class [Article] The Basics of GLSL 4.0 Shaders [Article] GLSL 4.0: Using Subroutines to Select Shader Functionality [Article]
Read more
  • 0
  • 0
  • 7466

article-image-basics-glsl-40-shaders
Packt
10 Aug 2011
11 min read
Save for later

The basics of GLSL 4.0 shaders

Packt
10 Aug 2011
11 min read
Shaders were first introduced into OpenGL in version 2.0, introducing programmability into the formerly fixed-function OpenGL pipeline. Shaders are implemented using the OpenGL Shading Language (GLSL). The GLSL is syntactically similar to C, which should make it easier for experienced OpenGL programmers to learn. Due to the nature of this text, I won't present a thorough introduction to GLSL here. Instead, if you're new to GLSL, reading through these recipes should help you to learn the language by example. If you are already comfortable with GLSL, but don't have experience with version 4.0, you'll see how to implement these techniques utilizing the newer API. However, before we jump into GLSL programming, let's take a quick look at how vertex and fragment shaders fit within the OpenGL pipeline. Vertex and fragment shaders In OpenGL version 4.0, there are five shader stages: vertex, geometry, tessellation control, tessellation evaluation, and fragment. In this article we'll focus only on the vertex and fragment stages. Shaders replace parts of the OpenGL pipeline. More specifically, they make those parts of the pipeline programmable. The following block diagram shows a simplified view of the OpenGL pipeline with only the vertex and fragment shaders installed. Vertex data is sent down the pipeline and arrives at the vertex shader via shader input variables. The vertex shader's input variables correspond to vertex attributes (see Sending data to a shader using per-vertex attributes and vertex buffer objects). In general, a shader receives its input via programmer-defined input variables, and the data for those variables comes either from the main OpenGL application or previous pipeline stages (other shaders). For example, a fragment shader's input variables might be fed from the output variables of the vertex shader. Data can also be provided to any shader stage using uniform variables (see Sending data to a shader using uniform variables). These are used for information that changes less often than vertex attributes (for example, matrices, light position, and other settings). The following figure shows a simplified view of the relationships between input and output variables when there are two shaders active (vertex and fragment). The vertex shader is executed once for each vertex, possibly in parallel. The data corresponding to vertex position must be transformed into clip coordinates and assigned to the output variable gl_Position before the vertex shader finishes execution. The vertex shader can send other information down the pipeline using shader output variables. For example, the vertex shader might also compute the color associated with the vertex. That color would be passed to later stages via an appropriate output variable. Between the vertex and fragment shader, the vertices are assembled into primitives, clipping takes place, and the viewport transformation is applied (among other operations). The rasterization process then takes place and the polygon is filled (if necessary). The fragment shader is executed once for each fragment (pixel) of the polygon being rendered (typically in parallel). Data provided from the vertex shader is (by default) interpolated in a perspective correct manner, and provided to the fragment shader via shader input variables. The fragment shader determines the appropriate color for the pixel and sends it to the frame buffer using output variables. The depth information is handled automatically. Replicating the old fixed functionality Programmable shaders give us tremendous power and flexibility. However, in some cases we might just want to re-implement the basic shading techniques that were used in the default fixed-function pipeline, or perhaps use them as a basis for other shading techniques. Studying the basic shading algorithm of the old fixed-function pipeline can also be a good way to get started when learning about shader programming. In this article, we'll look at the basic techniques for implementing shading similar to that of the old fixed-function pipeline. We'll cover the standard ambient, diffuse, and specular (ADS) shading algorithm, the implementation of two-sided rendering, and flat shading. in the next article, we'll also see some examples of other GLSL features such as functions, subroutines, and the discard keyword. Implementing diffuse, per-vertex shading with a single point light source One of the simplest shading techniques is to assume that the surface exhibits purely diffuse reflection. That is to say that the surface is one that appears to scatter light in all directions equally, regardless of direction. Incoming light strikes the surface and penetrates slightly before being re-radiated in all directions. Of course, the incoming light interacts with the surface before it is scattered, causing some wavelengths to be fully or partially absorbed and others to be scattered. A typical example of a diffuse surface is a surface that has been painted with a matte paint. The surface has a dull look with no shine at all. The following image shows a torus rendered with diffuse shading. The mathematical model for diffuse reflection involves two vectors: the direction from the surface point to the light source (s), and the normal vector at the surface point (n). The vectors are represented in the following diagram. The amount of incoming light (or radiance) that reaches the surface is partially dependent on the orientation of the surface with respect to the light source. The physics of the situation tells us that the amount of radiation that reaches a point on a surface is maximal when the light arrives along the direction of the normal vector, and zero when the light is perpendicular to the normal. In between, it is proportional to the cosine of the angle between the direction towards the light source and the normal vector. So, since the dot product is proportional to the cosine of the angle between two vectors, we can express the amount of radiation striking the surface as the product of the light intensity and the dot product of s and n. Where Ld is the intensity of the light source, and the vectors s and n are assumed to be normalized. You may recall that the dot product of two unit vectors is equal to the cosine of the angle between them. As stated previously, some of the incoming light is absorbed before it is re-emitted. We can model this interaction by using a reflection coefficient (Kd), which represents the fraction of the incoming light that is scattered. This is sometimes referred to as the diffuse reflectivity, or the diffuse reflection coefficient. The diffuse reflectivity becomes a scaling factor for the incoming radiation, so the intensity of the outgoing light can be expressed as follows: Because this model depends only on the direction towards the light source and the normal to the surface, not on the direction towards the viewer, we have a model that represents uniform (omnidirectional) scattering. In this recipe, we'll evaluate this equation at each vertex in the vertex shader and interpolate the resulting color across the face. In this and the following recipes, light intensities and material reflectivity coefficients are represented by 3-component (RGB) vectors. Therefore, the equations should be treated as component-wise operations, applied to each of the three components separately. Luckily, the GLSL will make this nearly transparent because the needed operators will operate component-wise on vector variables. Getting ready Start with an OpenGL application that provides the vertex position in attribute location 0, and the vertex normal in attribute location 1 (see Sending data to a shader using per-vertex attributes and vertex buffer objects). The OpenGL application also should provide the standard transformation matrices (projection, modelview, and normal) via uniform variables. The light position (in eye coordinates), Kd, and Ld should also be provided by the OpenGL application via uniform variables. Note that Kd and Ld are type vec3. We can use a vec3 to store an RGB color as well as a vector or point. How to do it... To create a shader pair that implements diffuse shading, use the following code: Use the following code for the vertex shader. #version 400 layout (location = 0) in vec3 VertexPosition; layout (location = 1) in vec3 VertexNormal; out vec3 LightIntensity; uniform vec4 LightPosition; // Light position in eye coords. uniform vec3 Kd; // Diffuse reflectivity uniform vec3 Ld; // Light source intensity uniform mat4 ModelViewMatrix; uniform mat3 NormalMatrix; uniform mat4 ProjectionMatrix; uniform mat4 MVP; // Projection * ModelView void main() { // Convert normal and position to eye coords vec3 tnorm = normalize( NormalMatrix * VertexNormal); vec4 eyeCoords = ModelViewMatrix * vec4(VertexPosition,1.0)); vec3 s = normalize(vec3(LightPosition - eyeCoords)); // The diffuse shading equation LightIntensity = Ld * Kd * max( dot( s, tnorm ), 0.0 ); // Convert position to clip coordinates and pass along gl_Position = MVP * vec4(VertexPosition,1.0); } Use the following code for the fragment shader. #version 400 in vec3 LightIntensity; layout( location = 0 ) out vec4 FragColor; void main() { FragColor = vec4(LightIntensity, 1.0); } Compile and link both shaders within the OpenGL application, and install the shader program prior to rendering. See Tips and Tricks for Getting Started with OpenGL and GLSL 4.0 for details about compiling, linking, and installing shaders. How it works... The vertex shader does all of the work in this example. The diffuse reflection is computed in eye coordinates by first transforming the normal vector using the normal matrix, normalizing, and storing the result in tnorm. Note that the normalization here may not be necessary if your normal vectors are already normalized and the normal matrix does not do any scaling. The normal matrix is typically the inverse transpose of the upper-left 3x3 portion of the model-view matrix. We use the inverse transpose because normal vectors transform differently than the vertex position. For a more thorough discussion of the normal matrix, and the reasons why, see any introductory computer graphics textbook. (A good choice would be Computer Graphics with OpenGL by Hearn and Baker.) If your model-view matrix does not include any non-uniform scalings, then one can use the upper-left 3x3 of the model-view matrix in place of the normal matrix to transform your normal vectors. However, if your model-view matrix does include (uniform) scalings, you'll still need to (re)normalize your normal vectors after transforming them. The next step converts the vertex position to eye (camera) coordinates by transforming it via the model-view matrix. Then we compute the direction towards the light source by subtracting the vertex position from the light position and storing the result in s. Next, we compute the scattered light intensity using the equation described above and store the result in the output variable LightIntensity. Note the use of the max function here. If the dot product is less than zero, then the angle between the normal vector and the light direction is greater than 90 degrees. This means that the incoming light is coming from inside the surface. Since such a situation is not physically possible (for a closed mesh), we use a value of 0.0. However, you may decide that you want to properly light both sides of your surface, in which case the normal vector needs to be reversed for those situations where the light is striking the back side of the surface (see Implementing two-sided shading). Finally, we convert the vertex position to clip coordinates by multiplying with the model-view projection matrix, (which is: projection * view * model) and store the result in the built-in output variable gl_Position. gl_Position = MVP * vec4(VertexPosition,1.0); The subsequent stage of the OpenGL pipeline expects that the vertex position will be provided in clip coordinates in the output variable gl_Position. This variable does not directly correspond to any input variable in the fragment shader, but is used by the OpenGL pipeline in the primitive assembly, clipping, and rasterization stages that follow the vertex shader. It is important that we always provide a valid value for this variable. Since LightIntensity is an output variable from the vertex shader, its value is interpolated across the face and passed into the fragment shader. The fragment shader then simply assigns the value to the output fragment. There's more... Diffuse shading is a technique that models only a very limited range of surfaces. It is best used for surfaces that have a "matte" appearance. Additionally, with the technique used above, the dark areas may look a bit too dark. In fact, those areas that are not directly illuminated are completely black. In real scenes, there is typically some light that has been reflected about the room that brightens these surfaces. In the following recipes, we'll look at ways to model more surface types, as well as provide some light for those dark parts of the surface.
Read more
  • 0
  • 0
  • 21501
article-image-glsl-40-using-subroutines-select-shader-functionality
Packt
10 Aug 2011
7 min read
Save for later

GLSL 4.0: Using Subroutines to Select Shader Functionality

Packt
10 Aug 2011
7 min read
OpenGL 4.0 Shading Language Cookbook Over 60 highly focused, practical recipes to maximize your OpenGL Shading language use         In many ways it is similar to function pointers in C. A uniform variable serves as the pointer and is used to invoke the function. The value of this variable can be set from the OpenGL side, thereby binding it to one of a few possible definitions. The subroutine's function definitions need not have the same name, but must have the same number and type of parameters and the same return type. A single shader could be written to provide several shading algorithms intended for use on different objects within the scene. When rendering the scene, rather than swapping shader programs (or using a conditional statement), we can simply change the subroutine's uniform variable to choose the appropriate shading algorithm as each object is rendered. Since performance is crucial in shader programs, avoiding a conditional statement or a shader swap can be very valuable. With subroutines, we can implement the functionality of a conditional statement or shader swap without the computational overhead. In the following image, we see an example of a rendering that was created using subroutines. The teapot on the left is rendered with the full ADS shading model, and the teapot on the right is rendered with diffuse shading only. A subroutine is used to switch between shader functionality. Getting ready As with previous recipes, provide the vertex position at attribute location 0 and the vertex normal at attribute location 1. Uniform variables for all of the ADS coefficients should be set from the OpenGL side, as well as the light position and the standard matrices. We'll assume that, in the OpenGL application, the variable programHandle contains the handle to the shader program object. How to do it... To create a shader program that uses a subroutine to switch between pure-diffuse and ADS shading, use the following code: Use the following code for the vertex shader: #version 400 subroutine vec3 shadeModelType( vec4 position, vec3 normal); subroutine uniform shadeModelType shadeModel; layout (location = 0) in vec3 VertexPosition; layout (location = 1) in vec3 VertexNormal; out vec3 LightIntensity; struct LightInfo { vec4 Position; // Light position in eye coords. vec3 La; // Ambient light intensity vec3 Ld; // Diffuse light intensity vec3 Ls; // Specular light intensity }; uniform LightInfo Light; struct MaterialInfo { vec3 Ka; // Ambient reflectivity vec3 Kd; // Diffuse reflectivity vec3 Ks; // Specular reflectivity float Shininess; // Specular shininess factor }; uniform MaterialInfo Material; uniform mat4 ModelViewMatrix; uniform mat3 NormalMatrix; uniform mat4 ProjectionMatrix; uniform mat4 MVP; void getEyeSpace( out vec3 norm, out vec4 position ) { norm = normalize( NormalMatrix * VertexNormal); position = ModelViewMatrix * vec4(VertexPosition,1.0); } subroutine( shadeModelType ) vec3 phongModel( vec4 position, vec3 norm ) { // The ADS shading calculations go here (see: "Using // functions in shaders," and "Implementing // per-vertex ambient, diffuse and specular (ADS) shading") ... } subroutine( shadeModelType ) vec3 diffuseOnly( vec4 position, vec3 norm ) { vec3 s = normalize( vec3(Light.Position - position) ); return Light.Ld * Material.Kd * max( dot(s, norm), 0.0 ); } void main() { vec3 eyeNorm; vec4 eyePosition; // Get the position and normal in eye space getEyeSpace(eyeNorm, eyePosition); // Evaluate the shading equation. This will call one of // the functions: diffuseOnly or phongModel. LightIntensity = shadeModel( eyePosition, eyeNorm ); gl_Position = MVP * vec4(VertexPosition,1.0); } Use the following code for the fragment shader: #version 400 in vec3 LightIntensity; layout( location = 0 ) out vec4 FragColor; void main() { FragColor = vec4(LightIntensity, 1.0); } In the OpenGL application, compile and link the above shaders into a shader program, and install the program into the OpenGL pipeline. Within the render function of the OpenGL application, use the following code: GLuint adsIndex = glGetSubroutineIndex( programHandle, GL_VERTEX_SHADER,"phongModel" ); GLuint diffuseIndex = glGetSubroutineIndex(programHandle, GL_VERTEX_SHADER, "diffuseOnly"); glUniformSubroutinesuiv( GL_VERTEX_SHADER, 1, &adsIndex); ... // Render the left teapot glUniformSubroutinesuiv( GL_VERTEX_SHADER, 1, &diffuseIndex); ... // Render the right teapot How it works... In this example, the subroutine is defined within the vertex shader. The first step involves declaring the subroutine type. subroutine vec3 shadeModelType( vec4 position, vec3 normal); This defines a new subroutine type with the name shadeModelType. The syntax is very similar to a function prototype, in that it defines a name, a parameter list, and a return type. As with function prototypes, the parameter names are optional. After creating the new subroutine type, we declare a uniform variable of that type named shadeModel. subroutine uniform shadeModelType shadeModel; This variable serves as our function pointer and will be assigned to one of the two possible functions in the OpenGL application. We declare two functions to be part of the subroutine by prefixing their definition with the subroutine qualifier: subroutine ( shadeModelType ) This indicates that the function matches the subroutine type, and therefore its header must match the one in the subroutine type definition. We use this prefix for the definition of the functions phongModel and diffuseOnly. The diffuseOnly function computes the diffuse shading equation, and the phongModel function computes the complete ADS shading equation. We call one of the two subroutine functions by utilizing the subroutine uniform shadeModel within the main function. LightIntensity = shadeModel( eyePosition, eyeNorm ); Again, this call will be bound to one of the two functions depending on the value of the subroutine uniform shadeModel, which we will set within the OpenGL application. Within the render function of the OpenGL application, we assign a value to the subroutine uniform with the following steps. First, we query for the index of each subroutine function using glGetSubroutineIndex. The first argument is the program handle. The second is the shader stage. In this case, the subroutine is defined within the vertex shader, so we use GL_VERTEX_SHADER here. The third argument is the name of the subroutine. We query for each function individually and store the indexes in the variables adsIndex and diffuseIndex. To select the appropriate subroutine function, we need to set the value of the subroutine uniform shadeModel. To do so, we call glUniformSubroutinesuiv. This function is designed for setting multiple subroutine uniforms at once. In our case, of course, we are setting only a single uniform. The first argument is the shader stage (GL_VERTEX_SHADER), the second is the number of uniforms being set, and the third is a pointer to an array of subroutine function indexes. Since we are setting a single uniform, we simply provide the address of the GLuint variable containing the index, rather than a true array of values. Of course, we would use an array if multiple uniforms were being set. In general, the array of values provided as the third argument is assigned to subroutine uniform variables in the following way. The ith element of the array is assigned to the subroutine uniform variable with index i. Since we have provided only a single value, we are setting the subroutine uniform at index zero. You may be wondering, "How do we know that our subroutine uniform is located at index zero? We didn't query for the index before calling glUniformSubroutinesuiv!" The reason that this code works is that we are relying on the fact that OpenGL will always number the indexes of the subroutines consecutively starting at zero. If we had multiple subroutine uniforms, we could (and should) query for their indexes using glGetSubroutineUniformLocation, and then order our array appropriately. Finally, we select the phongModel function by setting the uniform to adsIndex and then render the left teapot. We then select the diffuseOnly function by setting the uniform to diffuseIndex and render the right teapot. There's more... A subroutine function defined in a shader can match multiple subroutine types. In that case, the subroutine qualifier can contain a comma-separated list of subroutine types. For example, if a subroutine matched the types type1 and type2, we could use the following qualifier: subroutine( type1, type2 ) This would allow us to use subroutine uniforms of differing types to refer to the same subroutine function. Summary With subroutines we can implement the functionality of a conditional statement or shader swap without the computational overhead. Further resources on this subject: Tips and Tricks for Getting Started with OpenGL and GLSL 4.0 [Article] OpenGL 4.0: Using Uniform Blocks and Uniform Buffer Objects [Article] OpenGL 4.0: Building a C++ Shader Program Class [Article] The Basics of GLSL 4.0 Shaders [Article] GLSL 4.0: Discarding Fragments to Create a Perforated Look [Article]
Read more
  • 0
  • 0
  • 8671

article-image-oracle-integration-and-consolidation-products
Packt
09 Aug 2011
11 min read
Save for later

Oracle Integration and Consolidation Products

Packt
09 Aug 2011
11 min read
Oracle Information Integration, Migration, and Consolidation The definitive book and eBook guide to Oracle information integration and migration in a heterogeneous world Data services Data services are at the leading edge of data integration. Traditional data integration involves moving data to a central repository or accessing data virtually through SQL-based interfaces. Data services are a means of making data a 'first class' citizen in your SOA. Recently, the idea of SOA-enabled data services has taken off in the IT industry. This is not any different than accessing data using SQL, JDBC, or ODBC. What is new is that your service-based architecture can now view any database access service as a web service. Service Component Architecture (SCA) plays a big role in data services as now data services created and deployed using Oracle BPEL, Oracle ESB, and other Oracle SOA products can be part of an end-to-end data services platform. No longer do data services deployed in one of the SOA products have to be deployed in another Oracle SOA product. SCA makes it possible to call a BPEL component from Oracle Service Bus and vice versa. Oracle Data Integration Suite Oracle Data Integration (ODI)Suite includes the Oracle Service Bus to publish and subscribe messaging capabilities. Process orchestration capabilities are provided by Oracle BPEL Process Manager, and can be configured to support rule-based, event-based, and data-based delivery services. The Oracle Data Quality for Data Integrator, Oracle Data Profiling products, and Oracle Hyperion Data Relationship Manager provide best-in-class capabilities for data governance, change management hierarchical data management, and provides the foundation for reference data management of any kind. ODI Suite allows you to create data services that can be used in your SCA environment. These data services can be created in ODI, Oracle BPEL or the Oracle Service Bus. You can surround your SCA data services with Oracle Data Quality and Hyperion Data Relationship to cleanse your data and provide master data management. ODI Suite effectively serves two purposes: Bundle Oracle data integration solutions as most customers will need ODI, Oracle BPEL, Oracle Service Bus, and data quality and profiling in order to build a complete data services solution Compete with similar offerings from IBM (InfoSphere Information Server) and Microsoft (BizTalk 2010) that offer complete EII solutions in one offering The ODI Suite data service source and target data sources along with development languages and tools supported are: Data sourceData targetDevelopment languages and toolsERPs, CRMs, B2B systems, flat files, XML data, LDAP, JDBC, ODBCAny data sourceSQL, Java, GUI The most likely instances or use cases when ODI Suite would be the Oracle product or tool selected are: SCA-based data services An end-to-end EII and data migration solution Data services can be used to expose any data source as a service. Once a data service is created, it is accessible and consumable by any web service-enabled product. In the case of Oracle, this is the entire set of products in the Oracle Fusion Middleware Suite. Data consolidation The mainframe was the ultimate solution when it came to data consolidation. All data in an enterprise resided in one or several mainframes that were physically located in a data center. The rise of the hardware and software appliance has created a 'what is old is new again' situation; a hardware and software solution that is sold as one product. Oracle has released the Oracle Exadata appliance and IBM acquired the pure database warehouse appliance company Netezza, HP, and Microsoft announced work on an SQL Server database appliance, and even companies like SAP, EMC, and CICSO are talking about the benefits of database appliances. The difference is (and it is a big difference) that the present architecture is based upon open standards hardware platforms, operating systems, client devices, network protocols, interfaces, and databases. So, you now have a database appliance that is not based upon proprietary operating systems, hardware, network components, software, and data disks. Another very important difference is that enterprise software COTS packages, management tools, and other software infrastructure tools will work across any of these appliance solutions. One of the challenges for customers that run their business on the mainframe is that they are 'locked into' vendor- specific sorting, reporting, job scheduling, system management, and other products usually only offered from IBM, CA, BMC, or Compuware. Mainframe customers also suffer from a lack of choice when it comes to COTS applications. Since appliances are based upon open systems, there is an incredibly large software ecosystem. Oracle Exadata Oracle Exadata is the only database appliance that runs both data warehouse and OLTP applications. Oracle Exadata is an appliance that includes every component an IT organization needs to process information—from a grid database down to the power supply. It is a hardware and software solution that can be up and running in an enterprise in weeks instead of months for typical IT database solutions. Exadata provides high speed data access using a combination of hardware and a database engine that runs at the storage tier. Typical database solutions have to use indexes to retrieve data from storage and then pull large volumes of data into the core database engine, which churns through millions of rows of data to send a handful of row results to the client. Exadata eliminates the need for indexes and data engine processing by placing a lightweight database engine at the storage tier. Therefore, the database engine is only provided with the end result and does not have to utilize complicated indexing schemes, large amounts of CPU, and memory to produce the end results set. Exadata's capabilities to run large OLTP and data warehouse applications, or a large number of smaller OLTP and data warehouse applications on one machine make it a great platform for data consolidation. The first release of Oracle Exadata was based upon HP hardware and was for data warehouses only. The second release came out shortly before Oracle acquired Sun. This release was based upon Sun hardware, but ironically not on Sun Sparc or Solaris (Solaris is now an OS option). The Exadata source and target data sources along with development languages and tools supported are: Data sourceData targetDevelopment languages and toolsAny (depending upon the data source this may involve an intensive migration effort)Oracle ExadataSQL, PL/SQL, Java The most likely instances or use cases when Exadata would be the Oracle product or tool selected are: A move from hundreds of standalone database hardware and software nodes to one database machine A reduction in hardware and software vendors, and one vendor for hardware and software support Keepin It Real The database appliance has become the latest trend in the IT industry. Data warehouse appliances like Netezza have been around for a number of years. Oracle has been the first vendor to offer an open systems database appliance for both DW and OLTP environments. Data grid Instead of consolidating databases physically or accessing the data where it resides, a data grid places the data into an in-memory middle tier. Like physical federation, the data is being placed into a centralized data repository. Unlike physical federation, the data is not placed into a traditional RDBMS system (Oracle database), but into a high-speed memory-based data grid. Oracle offers both a Java and SQL-based data grid solution. The decision of what product to implement often depends on where the corporations system, database, and application developer skills are strongest. If your organization has strong Java or .Net skills and is more comfortable with application servers than databases, then Oracle Coherence is typically the product of choice. If you have strong database administration and SQL skills, then Oracle TimesTen is probably a better solution. The Oracle Exalogic solution takes the data grid to another level by placing Oracle Coherence, along with other Oracle hardware and software solutions, into an appliance. This appliance provides an 'end-to-end' solution or data grid 'in a box'. It reduces management, increases performance, reduces TCO, and eliminates the need for the customer having to build their own hardware and software solution using multiple vendor solutions that may not be certified to work together. Oracle Coherence Oracle Coherence is an in-memory data grid solution that offers next generation Extreme Transaction Processing (XTP). Organizations can predictably scale mission critical applications by using Oracle Coherence to provide fast and reliable access to frequently used data. Oracle Coherence enables customers to push data closer to the application for faster access and greater resource utilization. By automatically and dynamically partitioning data in memory across multiple servers, Oracle Coherence enables continuous data availability and transactional integrity, even in the event of a server failure. Oracle Coherence was purchased from Tangosol Software in 2007. Coherence was an industry-leading middle tier caching solution. The product only offered a Java solution at the time of acquisition, but a .NET offering was already scheduled before the acquisition took place. The Oracle Coherence source and target data sources along with development languages and tools supported are: Data sourceData targetDevelopment languages and toolsJDBC, any data source accessible through Oracle SOA adaptersCoherenceJava, .Net The most likely instances or use cases when Oracle Coherence would be the Oracle product or tool selected are: When it is necessary to replace custom, hand-coded solutions that cache data in middle tier Java or .NET application servers Your company's strengths are in application servers Java or .NET Oracle TimesTen Oracle TimesTen is a data grid/cache offering that has similar characteristics to Oracle Coherence. Both of the solutions offer a product that caches data in the middle tier for high throughput and high transaction volumes. The technology implementations are much different. TimesTen is an in-memory database solution that is accessed through SQL and the data storage mechanism is a relational database. The TimesTen solution data grid can be implemented across a wide area network (WAN) and the nodes that make up the data grid are kept in sync with your back end Oracle database using Oracle Cache Connect. Cache Connect is also used to automatically refresh the TimesTen database on a push or pull basis from your Oracle backend database. Cache Connect can also be used to keep TimesTen databases spread across the global in sync. Oracle TimesTen offers both read and update support, unlike other database in- memory solutions. This means that Oracle TimesTen can be used to run your business even if your backend database is down. The transactions that occur during the downtime are queued and applied to your backend database once it is restored. The other similarity between Oracle Coherence and TimesTen is that they both were acquired technologies. Oracle TimesTen was acquired from the company TimesTen in 2005. The Oracle TimesTen source and target data sources along with development languages and tools supported are: Data sourceData targetDevelopment languages and toolsOracleTimesTenSQL, CLI The most likely instances or use cases when Oracle TimesTen would be the Oracle product or tool selected are: For web-based read-only applications that require a millisecond responseand data close to where request is made For applications where updates need not be reflected back to the user in real-time Oracle Exalogic A simplified explanation of Oracle Exalogic is that it is Exadata for the middle tier application infrastructure. While Exalogic is optimized for enterprise Java, it is also a suitable environment for the thousands of third-party and custom Linux and Solaris applications widely deployed on Java, .NET, Visual Basic, PHP, or any other programming language. The core software components of Exalogic are WebLogic, Coherence, JRocket or Java Hotspot, and Oracle Linux or Solaris. Oracle Exalogic has an optimized version of WebLogic to run Java applications more efficiently and faster than a typical WebLogic implementation. Oracle Exalogic is branded with the Oracle Elastic cloud as an enterprise application consolidation platform. This means that applications can be added on demand and in real-time. Data can be cached in Oracle Coherence for a high speed, centralized, data grid sharable on the cloud. The Exalogic source and target data sources along with development languages and tools supported are: Data sourceData targetDevelopment languages and toolsAny data sourceCoherenceAny language The most likely instances or use cases when Exalogic would be the Oracle product or tool selected are: Enterprise consolidated application server platform Cloud hosted solution Upgrade and Consolidation of hardware or software Oracle Coherence is the product of choice for Java and .NET versed development shops. Oracle TimesTen is more applicable to database-centric and shops more comfortable with SQL.
Read more
  • 0
  • 0
  • 4765
Modal Close icon
Modal Close icon