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-jquery-user-interface-plugins-tooltip-plugins
Packt
27 Oct 2010
6 min read
Save for later

jQuery User Interface Plugins: Tooltip Plugins

Packt
27 Oct 2010
6 min read
  jQuery Plugin Development Beginner's Guide Build powerful, interactive plugins to implement jQuery in the best way possible Utilize jQuery's plugin framework to create a wide range of useful jQuery plugins from scratch Understand development patterns and best practices and move up the ladder to master plugin development Discover the ins and outs of some of the most popular jQuery plugins in action A Beginner's Guide packed with examples and step-by-step instructions to quickly get your hands dirty in developing high quality jQuery plugins         Read more about this book       (For more resources on jQuery, see here.) Before we get started, there is another little thing worth mentioning: provide many different opportunities to introduce new concepts and ideas, even while keeping the complexity of the whole plugin at a minimum. We can now go on to create our plugin, starting with basic functionalities, and subsequently adjusting its goals. We will add new, improved functionalities that, however, do not make the whole code look too difficult to understand—even after some time or for someone who's just starting out with jQuery. Tooltip plugins in general A lot has been said about tooltip plugins, but it's worth repeating the most important points with particular regard to the way tooltips are supposed to work, and how we want our tooltip to behave. First of all, we might want to get an idea of what tooltips look like and a sample of what we will accomplish by the end of this article. Here is an example: Also, with some more work and proper application of effects, images, and other relatively advanced techniques, we can also obtain something more complex and nicer looking, thus giving the user the chance to specify the style and behavior for the tooltip, as follows: The idea is actually very simple. The elements we have selected will trigger an event every time we hover the mouse pointer over them. The tooltip will then pop out, right at the mouse cursor position, retrieving the text portion from the title attribute of the said element. Finally, whenever we move the mouse over the same element, the plugin will move and follow the mouse cursor until it goes off the boundaries of the element. Positioning the tooltip The first problem we have to face is, of course, how to make the tooltip appear in the right position. It would be no trouble at all if we just had to make some text, image, or anything else show up. We've done it many times and it's no problem at all—just make their positioning absolute and set the right top and side distances. However, we need to take into account the fact that we don't know exactly where the mouse cursor might be and, as such, we need to calculate distances based upon the mouse cursor position itself. So, how can we do it? It's simple enough; we can use some of the JavaScript event properties to obtain the position. Unfortunately, Internet Explorer always tries to put a spoke in our wheel. In fact, the magnificent browser does not (according to this table, which is quite accurate: http://www.quirksmode.org/dom/w3c_cssom.html#mousepos) support pageX and pageY, which would normally return the mouse coordinates relative to the document. So we need to think about a workaround for Internet Explorer, as jQuery (from version 1.0.4 onwards) does not normalize some of the event properties according to W3C standards (http://api.jquery.com/category/events/event-object/). The following diagram (also provided in the " target="_blank">code bundle) should clarify what the visible viewport is (that is, the browser window—the red box): Whenever we scroll down, different parts of the document (blue) are shown through the browser window and hidden due to space constraints. The scroll height (green) is the part of the document currently not displayed. Custom jQuery selectors Suppose we have a page with some text written in, which also contains a few links to both internal pages (that is, pages on the same server) and external websites. We are presented with different choices in terms of which elements to apply the tooltip to (referring to links as an example, but they apply to any kind of element as well), as follows: All the links All the links with a specific class (for example, tooltip) All the links with the title attribute not empty All the links pointing to internal pages All the links pointing to external websites Combinations of the above We can easily combine the first three conditions with the others (and with themselves) using CSS selectors appropriately. For example: $("a"), all the links $("a.tooltip"), links having a tooltip class $("a[title]"), links with a title attribute (still have to check if empty) $("a.tooltip[title]"), links with a tooltip class and a title attribute As for internal and external pages, we have to work with jQuery selectors instead. Time for action – creating custom jQuery selectors Although jQuery makes it easy to select elements using standard CSS selectors, as well as some other selectors, jQuery's own selectors are the ones that help the developer to write and read code. Examples of custom selectors are :odd, :animated, and so on. jQuery also lets you create your own selectors! The syntax is as follows: // definition$.expr[':'].customselector = function(object, index,properties, list) { // code goes here};// call$("a:customselector") The parameters are all optional except for the first one (of course!), which is required to perform some basic stuff on the selected object: object: Reference to current HTML DOM element (not jQuery, beware!) index: Zero-based loop index within array properties: Array of metadata about the selector (the 4th argument contains the string passed to the jQuery selector) list: Array of DOM elements to loop through The return value can be either: true: Include current element false: Exclude current element Our selector (for external links detection) will then look, very simply, like the following code: $.expr[':'].external = function(object) { if(object.hostname) // is defined return(object.hostname != location.hostname); else return false;}; Also note that, to access the jQuery object, we have to use the following (since object refers to the DOM element only!): $.expr[':'].sample = function(object) { alert('$(obj).attr(): ' + $(object).attr("href") + 'obj.href: ' + object.href);}; Merging pieces together We have slowly created different parts of the plugin, which we need to merge in order to create a working piece of code that actually makes tooltips visible. So far we have understood how positioning works and how we can easily place an element in a determined position. Also, we have found out we can create our own jQuery selectors, and have developed a simple yet useful custom selector with which we are able to select links pointing to either internal or external pages. It needs to be placed at the top of the code, inside the closure, as we will make use of the dollar symbol ($) and it may conflict with other software.
Read more
  • 0
  • 0
  • 2255

article-image-tips-and-tricks-joomla-multimedia
Packt
27 Oct 2010
7 min read
Save for later

Tips and Tricks for Joomla! Multimedia

Packt
27 Oct 2010
7 min read
  Joomla! 1.5 Multimedia Build media-rich Joomla! web sites by learning to embed and display Multimedia content Build a livelier Joomla! site by adding videos, audios, images and more to your web content Install, configure, and use popular Multimedia Extensions Make your web site collaborate with external resources such as Twitter, YouTube, Google, and Flickr with the help of Joomla! extensions Follow a step-by-step tutorial to create a feature-packed media-rich Joomla! site         Read more about this book       (For more resources on Joomla!, see here.) Using another folder name for images in Joomla! Tip: If you do decide to use another folder name for your media directory, it is important to leave the current /images directory on the server as this can often be used by other components.   Organizing your content Tip: The organization of your website media content is of utmost importance. Just like with your Joomla! Articles, the correct structure of your files can save you time and frustration down the line when you want to easily find an image or media file.   Creating a new directory using Joomla! Media Manager Tip: While creating a new directory using Joomla! Media Manager, a forward slash is already pre-populated, so you only need to enter the name of the directory and nothing else.   Uploading and downloading files Tip: FTP programs offer you the most flexibility in managing your website files, but it is important to take care when using FTP programs. By connecting to your directory structure on the web server, you are navigating amongst core Joomla! files. You can download a file in a similar manner, or you might need to double-click on the file to start downloading it.   Uploading a new file with Joomla! Media Manager Tip: To upload a new file, make sure you are residing in the correct remote directory for upload. Browse to a file on your computer and simply drag this file over into your web browser.   Location of the Joomla! Template CSS files Tip: The Joomla! Template CSS file is usually located in the following directory /templates/yourtemplate/css/template.css. If you are using a pre-built Joomla! Template, you may see multiple CSS files inside the CSS directory. It is important to note that the names of these CSS files may differ between Joomla! Templates, but the template.css file is the standard naming convention for the main CSS file.   Adding an image using the Joomla! Article Image button Tip: Images can be easily added to new and existing Joomla! Articles (and Modules) by using the Image button, which is an extended editor plugin that is configured to be turned on with new Joomla! installations.   Adjusting your Joomla! template images Tip: The images for a Joomla! Template are generally located in the <Your Joomla Home Folder>/templates/<yourtemplate>/images directory. If you would like to adjust certain images in your template, the easiest way to do this is by viewing the template in your site browser and then making the necessary adjustments to the images.   Audio in Joomla! Articles Tip: It is good practice to make a blank .html file and upload it to your new audio directory. This will help stop anyone from being able to directly view all of the files inside your new audio directory. If you cannot create a new .html file, copy an existing Joomla! .html file that resides in the images directory.   Backup of site database Tip: Before installing any third-party code into your Joomla! website, make sure you take a backup of your site database and file set before installing extensions.   Dealing with complex HTML code Tip: Make sure you don't have your WYSIWYG editor turned on in your Joomla! Articles when entering complex HTML code into your Joomla! Articles.   Joomla! Plugin tags Tip: It is worth noting that Joomla! Plugin tags work with and without the WYSIWYG editor turned on.   Video podcast for Joomla! Tip: Creating a video podcast for Joomla! will allow you to display and promote your site or products to many users. Due to the nature of a podcast, they do not even have to be on your website to view the video podcasts, if produced correctly.   Multimedia enhancements with Shadowbox Tip: Shadowbox is a multi-use media plugin for your Joomla! website, so it may be all that you need for your multimedia requirements. The extension can be downloaded at http://extensions.joomla.org by searching for "Shadow".   Inserting custom code into your Joomla! Articles Tip: When starting to insert custom code into your Joomla! Articles, it is important to turn off WYSIWYG editors for your user account. This is because these editors cannot always process the custom HTML code. If the code is not recognized by the editor when loading in the content, it will remove the code altogether. The editor settings can be adjusted in the Global Configuration, or on a user basis via the User Manager.   Extension titles in Joomla! Extension Directory (JED) listings Tip: Due to lengthy URLs and the possibility that Joomla! Extension Directory (JED) listings could change at any time, search terms for the following extensions have been included, rather than direct links to the extensions. Performing a search on the JED for the related terms will help you find these extensions easily. The letters after the extension titles denote the following: M = Module C = Component P = Plugin L = Language T = Template   Publishing your Twitter tweets in your Joomla! site Tip: The JTweet extension is a module that publishes your Twitter tweets in your Joomla! site. The jTweet module now requires the JB Library plugin in order to work. The JB Library plugin loads the jQuery library automatically into the head of your template. The jQuery library is required for the jTweet module.   Mobilebot for Joomla 1.5 Tip: Mobilebot 1.0 for Joomla! 1.5.x can detect visitors using mobile devices and change the Joomla! Template automatically.   If you install an extension and do not use it, then remove it. Tip: Besides keeping your Joomla! site organized and uncluttered, it is best to remove code/files/folders from your server that are not being used. Leaving older code lying around can create security vulnerabilities.   Keep Joomla! up-to-date. Tip: Joomla! releases are made available for a reason and it is important to stay up-to-date with the software. With a well-structured design to the framework, there are now very few reasons to go near the core codework. Upgrading is usually an easy process, compared to some other web platforms. Remember to take a backup of your site files before performing any upgrade work, and to take regular backups whenever you can.   Content parameters Tip: The Article Manager in Joomla! contains a "Global Parameter" setting that sets the default options for your Joomla! Articles. You can override these within each article, but it is good practice to set these globally first, so you don't have to go back and adjust them later on.   HTTP status errors Tip: Joomla! uses the /templates/system/error.php file to handle several HTTP status errors, including "403 Forbidden", "404 Not Found", and "500 Internal Server" errors.   Uninstalling Extensions for Joomla! 1.5 Tip: Extensions for Joomla! 1.5 can be uninstalled easily by clicking on the Manage menu item on the Extension Manager page.   Summary In this article we highlighted some of the tips and tricks which can be of great use while working with Joomla! Multimedia. Further resources on this subject: Joomla! 1.5 Top Extensions Cookbook [Book] Joomla! Social Networking with JomSocial [Book] Joomla! 1.5 JavaScript jQuery [Book]
Read more
  • 0
  • 0
  • 1954

article-image-managing-articles-using-k2-content-construction-kit
Packt
27 Oct 2010
8 min read
Save for later

Managing Articles Using the K2 Content Construction Kit

Packt
27 Oct 2010
8 min read
  Joomla! 1.5 Cookbook The reader would benefit from the previous article on Installation and Introduction of K2 Working with items AKA articles The power of K2 is in the idea of categorizing your data, thus making it easier to manage. This will be especially helpful as your site grows in content. Many sites are fully article-based and it is not uncommon to see a site with thousands of articles on it. In this section, we'll tackle some more category-specific recipes. You may have noticed by now that data does not show up as typical articles do in Joomla!. In other words, if you added an item, set it published and featured, it may not be displayed on your site because you have not set up a menu item to your K2 content. K2 will need to be added to your menu structure to display the items (articles) in K2. The first recipe will take into account a site that has been in operation for a while and has K2 added to it. Getting ready This section assumes you have installed K2 and have content on your site. How to do it... Make sure you have a full backup of the database and the files. Log in as the administrator. Open the K2 Dashboard. If you DID NOT import your content in, (see the first recipe), do so now. If you have ALREADY imported your content using the Import Joomla! Content button - DO NOT import again. You run the risk of duplicating all your content. Should this happen, you can go in and delete the duplicate items. This can be a time-consuming process. Open Article Manager | Content | Article Manager. Select all your articles from the Article Manager and unpublish. Open Menu Manager and find your Home menu.Now that we have unpublished content, we'll need to replace the traditional Joomla! content items with K2 content. Opening the Menu Manager and selecting the Home menu item will show this: As you can see under K2 there are several choices to display content on your site. I will choose Item | Item as my display mode. This will show my visitors content in article form. You can pick what works best for you. Now returning to the instructions: After choosing Menu Item Type - click Save. Open K2 Dashboard. Select Items.Here is a partial screenshot of the items in our sample site. As you can see, it now starts to take on a bit more traditional Joomla! look. I can choose featured articles, publish them, or note. Set the order they show up in, the category they belong to and more. When you import content, from Joomla!, the articles retain their identity from Section and Category configuration. For example, the Joomla! Community Portal listed in the preceding screenshot as belonging to the category Latest has a parent category of News. When you imported the content, sections became the new K2 top-level categories. All existing categories become subcategories of the new top level categories. As we added K2 to a working site with sections and category data already in place, I want to make sure they inherit from our master category. In our sample site, we see the following screen when we open the K2 categories from the K2 Dashboard: We instruct the new top-level categories to follow the master category as the model for the rest. The following instructions will show you how. Open K2 Dashboard. Click Categories. Open your imported top-level categories - for this site it's About Joomla! and News. Each of these has sub-categories. Click About Joomla! (or your equivalent). Change the Inherit parameter options from category to MASTER CATEGORY USE AS INHERIT ONLY. Make sure the Parent category stays set to –None--. Click Save.When done, it will look like this: Extra fields Did you notice the Associated "Extra Fields Group" is set to - None - ? You can change this parent category group to use an extra fields group and still keep the master category parameters. Each of the subcategories will inherit from the master category. By doing this, you can still control all the categories parameters simply by changing the master category. How it works... The category system as described here for K2 is a giant access-control system allowing you the flexibility to structure your site and data as you need. It also offers a means to control the 'look and feel' of the articles from a central place. When you import a Joomla! site into K2 you bring all the sections, content, articles, and other associated parts into it. Sections become new parent categories and the old categories become subcategories. This can be a bit confusing at first. One suggestion is to write out on paper what you want the site to look like, and then lay out your categories. You might find that the structure you had can be more user-friendly using K2 and you will want to change. This category system offers you nearly unlimited means to nest articles. In essence, a category can have unlimited categories under it. There is a limit to this in terms of management, but you get the idea. There's more... Using tags in K2 will give you the ability to improve your Search Engine Optimization or SEO on your site. Additionally, the use of tags will allow you to give your users the ability to follow the tags to other articles. In this section we'll review how to use Tags in K2. Tags are keywords or terms that are assigned to your content. This enables your visitors to quickly locate what they need by one word descriptions. Using Tags in K2 Tags can be created before an article is written or on the fly. I prefer on the fly as it will match the article. You can think of a tag almost as a dynamic index. Every time a tag is added to an article, it will show up in the K2 Tag Cloud module if you are using it. The more a single tag, such as Joomla!, is used in the content, the larger it appears in the K2 Cloud module. K2 Tag Clouds can benefit your search engine optimization and a navigational element. Here is an example of our K2 Tag Cloud: This is an image of our K2 Tag Cloud module. The more often a tag is added to an article, the larger it appears. Setting up your site for Tag Clouds K2 installs the K2 Tools module by default. The module has many functions, but for our purposes here, we'll use the Tag module. Log in to the Administrator Console of Joomla!. Click Extensions | Module Manager. Click New to create a new module. Find this for your new item: Once in there, give it a name and select its module location. On the right under Parameters, pull down the Select module functionality drop-down list as follows: Select Tag Cloud as shown in the preceding screenshot. Leave all the root categories set for none - this will enable K2 to pull in all the categories. Click Save. This particular module, has many functions and you can set up a new module to use any of the great tools built into it. Next you will want to add some tags to articles. As I said at the beginning of this article, you have two different ways to do this. You may add them to the article or you may add them to the Tag Manager. Let's quickly review the latter method. Open K2 Dashboard. Click Tags. You may see a list of tags there. If you wish to delete them, simply check the ones you want to remove and click Delete in the upper right-hand corner. Otherwise just leave them. Click New which will open the Details box. Fill in the tag; make sure it's published and click Save. This is an example of a filled out tag box (before save). Adding Tags on the fly This model allows you to tag the content as soon as you create it. If there are tags available, already such as those from the previous step, then you can add them. Open K2 Dashboard. Click Items. Select an item or click New to create an item. The field Tags will be blank, you can start to type in a field, such as K2 Content Creation Kit (as shown in the preceding screenshot). If it exists, then it will be available to be able to click and add. If there are no tags available, then simply type one in and click Return or add a comma. Here is an example item with tags. Here we have four tags, Security x, PHP x, Joomla x, K2 Content Creation Kit x. Any item (article) that has these tags will be easily found by both users and search bots. Let's see how our Tag Cloud looks now: You probably notice the changes, especially the addition of the new tag K2 Content Creation Kit. Clicking on that tag will yield two articles, and clicking on the Security tag yields three. Search engines can follow these links to better categorize your site. Users can get a sense of what is more important in terms of content from your site and it helps them navigate. Closing on this, I strongly suggest you spend time picking tags that are important on your site and is relevant to the purpose of it.
Read more
  • 0
  • 0
  • 3516

article-image-postgresql-9-reliable-controller-and-disk-setup
Packt
27 Oct 2010
10 min read
Save for later

PostgreSQL 9: Reliable Controller and Disk Setup

Packt
27 Oct 2010
10 min read
Accelerate your PostgreSQL system Learn the right techniques to obtain optimal PostgreSQL database performance, from initial design to routine maintenance Discover the techniques used to scale successful database installations Avoid the common pitfalls that can slow your system down Filled with advice about what you should be doing; how to build experimental databases to explore performance topics, and then move what you've learned into a production database environment Covers versions 8.1 through 9.0 PostgreSQL uses a Write-Ahead Log (WAL) to write data in a way that survives a database or hardware crash. This is similar to the log buffer or REDO log found in other databases. The database documentation covers the motivation and implementation of the WAL at http://www.postgresql.org/docs/current/ static/wal.html To quote from that introduction: WAL's central concept is that changes to data files (where tables and indexes reside) must be written only after those changes have been logged, that is, after log records describing the changes have been flushed to permanent storage. This procedure ensures that if your application has received a COMMIT for a transaction, that transaction is on permanent storage, and will not be lost even if there is a crash. This satisfies the durability portion of the ACID (atomicity, consistency, isolation, durability) expectations databases aim to satisfy. Write-back caches The CPUs and memory in your server are quite fast compared to its disk drives. Accordingly, making the rest of the system wait for the disks, particularly when things need to be written out, can drag overall performance down heavily. Systems that wait for the disks to complete their writes before moving into their next task are referred to as having a write-through cache. While the data may be stored temporarily in a memory cache, until it's made it all the way through to the physical disk, any write an application requested isn't considered complete. The normal solution to making that faster is to introduce a different type of write cache between the program doing the writing and disks. A write-back cache is one where data is copied into memory, and then control returns to the application that requested the write. Those writes are then handled asynchronously, at some future time dictated by the design of the write-back cache. It can take minutes before the data actually makes it to disk. When PostgreSQL writes information to the WAL, and sometimes when it writes to the regular database files too, that information must be "flushed to permanent storage" in order for the database's crash corruption defense mechanism to work. So what happens if you have a write-back cache that says the write is complete, but it really isn't? People call these lying drives, and the result can be very bad: If you have a system with a write-back cache, and a system crash causes the contents of that write-back cache to be lost, this can corrupt a PostgreSQL database stored on that drive and make it unusable. You can discover it takes expert intervention to even get the database to start again, and determining what data is damaged will be difficult. Consider the case where you have committed a transaction. Details of that new transaction might be spread across two data blocks on the drive. Now, imagine that one of those made it to disk before the system crashed, but the other didn't. You've now left the database in a corrupted state: one block refers to a transaction that doesn't exist where it's supposed to in the other block. Had at least all of the data blocks related to the WAL been written properly, the database WAL could correct this error after the crash. But the WAL protection only works if it can get honest information about whether information has been written to the disks properly or not, and the "lying" write-back caches do not report that. Sources of write-back caching Servers are filled with write caches you need to be aware of: Operating system write cache. This cache can easily be gigabytes in size. Typically you can flush data out of this cache by forcing a "sync" operation on the block that needs to be stored on disk. On POSIX systems (which includes all UNIX-like ones), this is done with the fsync or fdatasync calls. In some cases, it's possible to write directly in a sync mode, which is effectively a write followed by fsync. The postgresql.conf setting wal_sync_method controls which method is used, and it's possible to disable this altogether to optimize for speed instead of safety. Disk controller write cache. You'll find a write cache on most RAID controller cards, as well as inside external storage such as a SAN. Common sizes right now are 128 MB to 512 MB for cards, but gigabytes are common on a SAN. Typically controllers can be changed to operate in the completely writethrough mode, albeit slowly. But by default, you'll normally find them in write-back mode. Writes that can fit in the controller's cache are stored there, the operating system is told the write is completed, and the card writes the data out at some future time. To keep this write from being lost if power is interrupted, the card must be configured with a battery. That combination is referred to as a battery-backed write cache (BBC or BBWC). Disk drive write cache. All SATA and SAS disks have a write cache on them that on current hardware is 8 MB to 32 MB in size. This cache is always volatile: if power is lost, any data stored in there will be lost and they're always write-back caches if enabled. How can you make sure you're safe given all these write-back caches that might lose your data? There are a few basic precautions to take: Make sure whatever file system you're using properly implements fsync calls, or whatever similar mechanism is used, fully. Monitor your driver controller battery. Some controller cards will monitor their battery health, and automatically switch from write-back to writethough mode when there is no battery or it's not working properly. That's a helpful safety measure, but performance is going to drop hard when this happens. Disable any drive write caches. Most hardware RAID controllers will do this for you, preferring their own battery-backed caches instead. Disk controller monitoring When you have a RAID controller card with a battery-backed cache, you probably expect you'll need to monitor the card to determine when disks fail. But monitoring controller battery health is an equally critical aspect of maintaining a reliable database system when you're using this technology. If the battery fails and you're using it in write-back mode, your writes are not safe. Similarly, if your power fails, you should prefer shutting the database server down after a few minutes of power loss to trying to keep it going. Integrating in power monitoring via a UPS or similar mechanism should be part of your database server configuration, so that a short outage results in an orderly shutdown. Consider the purpose of the controller battery to protect yourself from really unexpected outages, like someone tripping over the power cord. Even if the manufacturer claims the controller battery will last through days of downtime, that's not a good reason to believe you'll actually be safe for an extended outage. You should consider the battery as something you'd prefer to only use for some number of minutes of protection. That may be the reality, particularly in a case where the battery is older and has lost much of its capacity, and some controller batteries don't start out with very much capacity. Be sure to run your own tests rather than blindly believing the manufacturer specifications: your data depends on it. Better RAID controllers will automatically disable write-back mode if their battery stops working normally. If performance suddenly drops on an older server, this is one potential cause. Also don't forget that every UPS has a battery that degrades over time as well. That's all the more reason to arrange an orderly shutdown of your server during a power outage, rather than optimistically presuming you can keep it running until power returns. Disabling drive write caches If your card doesn't disable all the drive write caches, or if you're using a software RAID approach, you'll need to turn the caches off yourself. The best way to do this is to see if it's possible to change the default write cache state using the utilities provided by the drive manufacturer. You should be able to do this through software as well. Here is a sample session from a Linux system checking the write cache, toggling it off, confirming that change took, and then toggling it on again: # hdparm -I /dev/sda | grep "Write cache" * Write cache # sudo hdparm -W 0 /dev/sda /dev/sda: setting drive write-caching to 0 (off) write-caching = 0 (off) # hdparm -I /dev/sda | grep "Write cache" Write cache # hdparm -W 1 /dev/sda /dev/sda: setting drive write-caching to 1 (on) write-caching = 1 (on) Only the -W 0 configuration is completely safe for database use. The PostgreSQL WAL documentation suggests similar commands to use for other operating systems. Performance impact of write-through caching If you don't have a battery-backed write cache, and therefore can't utilize some memory-based cache to accelerate fsync writes, commit performance on your database can be quite bad. The worst-case here is where you have a single client that is issuing a commit after every statement it executes. The reality of how a hard drive works means that individual writes happen once each time the drive spins around. Here are the measurements for the common drive speeds available right now, with computed maximum commit rate:     Rotation speed Rotation time (ms) Max commits/second 5400 11.1 90 7200 8.3 120 10000 6.0 166 15000 4.0 250 It's important to realize how limiting this can be: If you have a common 7200 rpm hard drive, no single client can commit more than 120 transactions/second in any situation where all that's available is a write-back cache. It doesn't matter how many disks you have in a RAID array, or how you configure your software. You must have hardware with a battery, enabling a non-volatile write-back cache, in order to safely exceed this limit. Some PostgreSQL installs use a RAID controller card just for this purpose, to provide a BBWC, in Just a Bunch of Disks (JBOD) mode—where no RAID is being done on the controller at all. Sometimes disks are used directly, and others layer software RAID on top, which can have some advantages compared to hardware RAID. If you have more than one client, you'll get more done per commit. It's normal to see >500 committed transactions per second if you have a larger number of clients all committing regularly, because each flushed disk write will include any queued up commit requests from other clients, too. The other common technique here is to batch commits into larger pieces, perhaps going 1000 records at a time rather than a single one, in order to reduce the average impact of commit latency. Another approach for accelerating systems that don't have a usable write cache is asynchronous commit. Summary In this article we saw how accidentally using volatile write-back caching in disk controllers and drives can easily introduce database corruption. Further resources on this subject: UNIX Monitoring Tool for PostgreSQL [Article] Server Configuration Tuning in PostgreSQL [Article] PostgreSQL 9: Balancing Hardware Spending [Article]
Read more
  • 0
  • 0
  • 2665

article-image-authorizing-user-access-bpel-process
Packt
27 Oct 2010
6 min read
Save for later

Authorizing User Access to BPEL Process

Packt
27 Oct 2010
6 min read
Propagating user identity to a BPEL process To propagate user identity from the UsernameToken to the BPEL process, we will first have to extract that identity from the UsernameToken. Then, we will propagate it to the BPEL process. We will enable identity extraction and propagation through policy set bindings. Policy set bindings will contain token consumer definition for identity extraction and caller definition for identity propagation. Extracting user identity from UsernameToken To enable the extraction of user identity from UsernameToken, we have to define a new policy set binding. We have to set this binding to use a UsernameToken consumer that will be performing the extraction. To achieve this, we have to complete the following steps: First, we have to create a new policy set binding. We will go to the Integrated Solutions Console and expand Services | Policy Sets | General provider policy set bindings: In the General provider policy set bindings list, we can see provided bindings. Apart from BPC Web Service – Provider, which is used for the Business Process Choreographer web service API, all bindings are only samples. Click on the New… button to create a new binding: (Move the mouse over the image to enlarge.) For the new binding, we need to provide a name, description (optional), and policies that the binding refers to (in our example, WS-Security). For the Bindings configuration name, we will enter WSS UsernameToken to Caller Propagation and Propagate WS-Security UsernameToken authentication information to the runtime environment for Description. Now, expand the Add drop-down menu and select WS-Security to add a WS-Security policy: Next, we will define the token consumer for identity extraction. After clicking on the WS-Security, we will select the Authentication and protection link to define the UsernameToken consumer: Under Authentication tokens we have: Protection tokens, which sign messages to provide integrity or encrypt messages to provide confidentiality Authentication tokens, which are used to provide or assert (propagate) the identity Detailed signing and encryption settings can be defined in the Request message signature and encryption protection and Response message signature and encryption protection sections. To add a UsernameToken consumer, we will expand the New Token drop-down menu in Authentication tokens and select Token Consumer: We created a new token consumer. If we want it to be the UsernameToken consumer, we have to specify its name, select UsernameToken for its type, and select the appropriate application login. Application login is basically a Java class that performs the actual authentication of the user based on his/her credentials provided in the token. So, for the token name, we will enter WSS UsernameToken Consumer and for its type, we will select UsernameToken v1.0. We will use version 1.0, as it is sufficient for our example. UsernameToken profile v1.1 contains some additional extensions that are used for deriving keys from the password for protecting message contents in the sense of integrity or confidentiality.After we have selected the Token type, the Local part field is automatically filled in for us. If we would have chosen some other authentication token (for example LTPA), Namespace URI would be automatically filled in for us. We leave JAAS login at the default value (wss.consume.unt), because it is a default Java Authentication and Authorization Service system login for UsernameToken consumers. All described details are shown in the following screenshot: Now, we should save changes made in the console to the master configuration, as shown in the following screenshot: We have created a policy set binding with a UsernameToken consumer that can extract user identity from the token. Propagating an extracted user identity to a BPEL process With the UsernameToken consumer we have defined a user identity extraction from the UsernameToken. Now we have to define a Caller that will propagate the extracted identity to the succeeding components: We will return to the WS-Security settings using the breadcrumb navigation and select the Caller link: We will click on the New button to create a new Caller. We have to specify its name, identity local part (the URL from the token specification that tells from which type of token the identity should be propagated), and application login (the set of Java classes that takes care of token propagation). For the Name enter WSS UsernameToken v1.0 Caller and for the Caller identity local part enter the URL http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#UsernameToken. This is the URL defined in the UsernameToken profile v1.0 to uniquely identify UsernameToken. We will leave JAAS login at default (wss.caller), because it is a default Java Authentication and Authorization Service system login for the UsernameToken caller. Click on OK to finish creating the Caller. We have successfully defined a policy set binding for propagating the identity from the UsernameToken to the succeeding components. We should now save the changes made through editors to the master configuration. Assigning a policy set binding to propagate an identity to a provider All that is left to achieve the propagation of the user identity to the BPEL process is to assign the defined policy set binding to the web service that exports our BPEL process. This procedure is necessary after each (re)deploy of the BPEL process to the server: Let us assign the policy set binding to the web service provider that represents the web service export of our BPEL process. In the Integrated Solutions Console, expand Services, and click on Service providers: In the Service providers list we can see several providers. We will definitely see two: BFMJAXWSService and HTMJAXWSService. These two providers represent the already mentioned Business Process Choreographer web service APIs, for working with BPEL processes and human tasks respectively.We will also see our TravelApproval provider. We will click on TravelApprovalWS_TravelApprovalPTHttpService: In General Properties, we can see a fully qualified XML name of the service. We can look at the service's WSDL document under Additional Properties. There we can also locate the application and the module of the service. In the Policy Set Attachments table, we can see the attached policies to this service provider. There is already the WSS UsernameToken only policy set attached to the provider. We achieved this through the definition in the assembly diagram earlier in this example.Now, we have to add the policy set binding that contains Caller to propagate a user identity to the BPEL process. We will click on the checkbox next to TravelApprovalWS_TravelApprovalPTHttpService. We will expand the Assign Binding drop-down menu and select WSS UsernameToken to Caller Propagation: With this, we have attached the policy set binding with the proper Caller defined and enabled the user identity propagation. Our configuration should look like the one shown in the following screenshot: We will now save changes made to the master configuration. So far, we have configured everything necessary for the propagation of the user identity to the BPEL process. For the configuration to start working in the previous steps, we assigned the defined policy set binding to the web service export of our BPEL process.
Read more
  • 0
  • 0
  • 1670

article-image-php-5-social-networking-implementing-public-messages
Packt
26 Oct 2010
7 min read
Save for later

PHP 5 Social Networking: Implementing Public Messages

Packt
26 Oct 2010
7 min read
PHP 5 Social Networking Create a powerful and dynamic Social Networking website in PHP by building a flexible framework   Build a flexible Social Networking framework using PHP which can be extended to fit the needs of any Social Networking site Develop a suitable structure for our framework, with MVC to structure the architecture and a Registry to store core Objects Allow users to connect and communicate with each other using communication with friends list, flexible user profiles, messages, discussions, and much more Plan marketing and scaling strategies, to entice more users and ensure the site can cope with the demand Packed with real-world code and clear explanation, this book uses an ongoing case study for creating a Social Networking framework Throughout the course of this article we will be using a social networking site for keepers of pet dinosaurs (of course nobody owns a real pet dinosaur, but for the sake of this article, let's pretend!), which we will call DinoSpace. Public messages The status stream fully supports public messages and streaming them to the Dino Space members. What we don't yet have, however, is support for users to post messages on the profiles of other users, so, let's add that in now. Controller A user should only be able to post a message on another user's profile if they are connected. The post message form should only be displayed if the users are connected. Similarly, a public message post should only be processed if the two users are connected. The controller also needs to display messages that have been posted on a user's profile too. Displaying profile messages If we look at our Profilestatusescontroller (controllers/profile/ profilestatusescontroller.php), in the listRecentStatuses method, we have our query for listing recent profile statuses: $sql = "SELECT t.type_reference, t.type_name, s.*, p.name as poster_name FROM statuses s, status_types t, profile p WHERE t.ID=s.type AND p.user_id=s.poster AND p.user_id={$user} ORDER BY s.ID DESC LIMIT 20"; At the moment, this query pulls in any posts on a user's profile by the user whose profile it is. If that user has made a post on someone else's profile, the message instead shows on the user's own profile, which we don't want. We need to change this to pull in the profiles table twice, once for the user who made the post, and again for the user whose profile is being viewed. We will also want to only pull in posts made on the user's profile, and not posts made by the user on another user's profile (though this is something we can expand on in the future, perhaps to indicate that a user has made a post on the profile of another user). The following query should meet our requirements nicely: $sql = "SELECT t.type_reference, t.type_name, s.*, pa.name as poster_name FROM statuses s, status_types t, profile p, profile pa WHERE t.ID=s.type AND p.user_id=s.profile AND pa.user_id=s.poster AND p.user_id={$user} ORDER BY s.ID DESC LIMIT 20"; Now, if we view a user's profile, we see their own status updates, and messages posted on their profile by other users, as shown in the following screenshot: Displaying the post message box The listRecentStatuses method we were just editing is the method we need to edit to display the post message box. This box should only be displayed if the user is logged in, and is connected to the user. If the user is viewing their own profile, then they should see a box to update their own status: // post status / public message box if( $this->registry->getObject('authenticate')->isLoggedIn() == true ) { $loggedInUser = $this->registry->getObject('authenticate')- >getUser()->getUserID(); If the logged in user is viewing their own profile, then we add the update template to the view, so they can update their status: if( $loggedInUser == $user ) { $this->registry->getObject('template')->addTemplateBit('status_ update', 'profile/statuses/update.tpl.php' ); } else { If the user isn't viewing their own profile, but is logged in, we get any connections the user has: require_once( FRAMEWORK_PATH . 'models/relationships.php' ); $relationships = new Relationships( $this->registry ); $connections = $relationships->getNetwork( $user, false ); if( in_array( $loggedInUser, $connections ) ) { If the user is connected to the user whose profile they are viewing, then we allow them to post a message on the users profile with the post template: $this->registry->getObject('template')->addTemplateBit( 'status_update', 'profile/statuses/post.tpl.php' ); } else { If the user isn't connected to the user, or isn't logged in, then we simply remove the template tag from the view so they don't see any update or post box on the page: $this->registry->getObject('template')->getPage()- >addTag( 'status_update', '' ); } } } else { $this->registry->getObject('template')->getPage()- >addTag( 'status_update', '' ); } Now, we need to process status updates and profile posts, and create the templates that make up the final aspect of our view. Process a new message The same logic that we used to determine whether the user should see a post form is what we need to use to determine if we should process a status update, or public message submission. Status model To save the status update or public profile post in the database, we will need a status model; as with our previous models, this simply needs to represent the fields from the database, with setter methods for these fields, and a save method to insert a new record into the database. In the future, we may wish to extend this to pull in statuses from the database, and save changes to them, as well as deleting statuses, perhaps if the owner of the message or the owner of the profile the message was posted on wishes to edit or delete it. The following is suitable code for our status model (models/status.php): <?php /** * Status model */ class Status { /** * The registry object */ private $registry; /** * Statuses ID */ private $id; /** * Poster of the status update / profile message */ private $poster; /** * The profile the status update / profile message was posted on */ sprivate $profile; /** * Type of status */ private $type; /** * The update / profile message itself */ private $update; /** * Reference for the type of status */ private $typeReference = 'update'; /** * Constructor * @param Registry $registry the registry object * @param int $id ID of the status update / profile message * @return void */ public function __construct( Registry $registry, $id=0 ) { $this->registry = $registry; $this->id = 0; } /** * Set the poster of the status / profile message * @param int $poster the id of the poster * @return void */ public function setPoster( $poster ) { $this->poster = $poster; } /** * Set the profile that the message / status is posted on * @param int $profile the profile ID * @return void */ public function setProfile( $profile ) { $this->profile = $profile; } /** * Set the status / profile message itself * @param String $status * @return void */ public function setStatus( $status ) { $this->status = $status; } /** * Set the type of status / profile message * @param int $type * @return void */ public function setType( $type ) { $this->type = $type; } /** * Set the type reference, so we can get the type ID from the database * @param String $typeReference the reference of the type * @return void */ public function setTypeReference( $typeReference ) { $this->type = $typeReference; } /** * Generate the type of status based of the type reference * @return void */ public function generateType() { $sql = "SELECT * FROM status_types WHERE type_reference='{$this->typeReference}'"; $this->registry->getObject('db')->executeQuery( $sql ); $data = $this->registry->getObject('db')->getRows(); $this->type = $data['ID']; } /** * Save the status / profile message * @return void */ public function save() { if( $this->id == 0 ) { $insert = array(); $insert['update'] = $this->status; $insert['type'] = $this->type; $insert['poster'] = $this->poster; $insert['profile'] = $this->profile; $this->registry->getObject('db')- >insertRecords( 'statuses', $insert ); $this->id = $this->registry->getObject('db')->lastInsertID(); } } } ?> Now that we have some functionality to easily insert the status into the database, we need to update our profile controller to process the new status update.
Read more
  • 0
  • 0
  • 6649
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-php-5-social-networking-private-messages
Packt
26 Oct 2010
7 min read
Save for later

PHP 5 Social Networking: Private Messages

Packt
26 Oct 2010
7 min read
PHP 5 Social Networking We obviously need to keep private messages separate from the rest of the site, and ensure that they are only accessible to the sender and the receiver. While we could alter the public messages feature developed earlier, this would raise a few issues, such as being more difficult to tell whether the message being sent or read was private, and when using the Internet in a public area, the message would be shown on the area of the social network the user would most likely be visiting, which isn't ideal for private information. Because private messages will be separate from statuses, and won't need to make use of other media types to make them more interesting (though, we could set them up to make use of other media if we wanted), it makes sense for us to also use separate database tables and models for this feature. Database Our database needs provisions for the sender of the message, the recipient of the message, the subject of the message, and of course the message itself. We should also provide for if the message has been read, when the message was sent, and an ID for the message. The following illustrates a suitable structure for a messages table in our database:   Field Type Description ID Integer, Autoincrement, Primary Key Reference ID for the message Sender Integer The sender of the message Recipient Integer The recipient of the message Subject Varchar The subject the message relates to Sent Timestamp When the message was sent Message Longtext The contents of the message itself Read Boolean Indicates whether the message has been read or not More than one recipient? This database structure, and the code that follows, only supports one recipient per message. Our users might want to send to more than one recipient—feel free to add this functionality if you wish. Message model As with the majority of our database access, we require a model (models/message. php) to create, update, and retrieve message-related data from the database and encapsulate it within itself. It would also be helpful if the model pulled in a little more information from the database, including: A more user friendly representation of the date (we can get this via the MySQL DATE_FORMAT function) The name of the sender, by joining the messages table to the profile table The name of the recipient, by joining the messages table to the profile table again The first part of our model simply defines the class variables: <?php /** * Private message class */ class Message { /** * The registry object */ private $registry; /** * ID of the message */ private $id=0; /** * ID of the sender */ private $sender; /** * Name of the sender */ private $senderName; /** * ID of the recipient */ private $recipient; /** * Name of the recipient */ private $recipientName; /** * Subject of the message */ private $subject; /** * When the message was sent (TIMESTAMP) */ private $sent; /** * User readable, friendly format of the time the message was sent */ private $sentFriendlyTime; /** * Has the message been read */ private $read=0; /** * The message content itself */ private $message; The constructor takes the registry and ID of the message as parameters, if the ID has been defined, then it queries the database and sets the class variables. The database query here also formats a copy of the date into a friendlier format, and looks up the names of the sender and recipient of the message: /** * Message constructor * @param Registry $registry the registry object * @param int $id the ID of the message * @return void */ public function __construct( Registry $registry, $id=0 ) { $this->registry = $registry; $this->id = $id; if( $this->id > 0 ) { $sql = "SELECT m.*, DATE_FORMAT(m.sent, '%D %M %Y') as sent_friendly, psender.name as sender_name, precipient.name as recipient_name FROM messages m, profile psender, profile precipient WHERE precipient.user_id=m.recipient AND psender.user_id=m.sender AND m.ID=" . $this->id; $this->registry->getObject('db')->executeQuery( $sql ); if( $this->registry->getObject('db')->numRows() > 0 ) { $data = $this->registry->getObject('db')->getRows(); $this->sender = $data['sender']; $this->recipient = $data['recipient']; $this->sent = $data['sent']; $this->read = $data['read']; $this->subject = $data['subject']; $this->message = $data['message']; $this->sentFriendlyTime = $data['sent_friendly']; $this->senderName = $data['sender_name']; $this->recipientName = $data['recipient_name']; } else { $this->id = 0; } } } Next, we have setter methods for most of the class variables: /** * Set the sender of the message * @param int $sender * @return void */ public function setSender( $sender ) { $this->sender = $sender; } /** * Set the recipient of the message * @param int $recipient * @return void */ public function setRecipient( $recipient ) { $this->recipient = $recipient; } /** * Set the subject of the message * @param String $subject * @return void */ public function setSubject( $subject ) { $this->subject = $subject; } /** * Set if the message has been read * @param boolean $read * @return void */ public function setRead( $read ) { $this->read = $read; } /** * Set the message itself * @param String $message * @return void */ public function setMessage( $message ) { $this->message = $message; } The save method takes the class variables that directly relate to the messages table in the database and either inserts them as a new record, or updates the existing record: /** * Save the message into the database * @return void */ public function save() { if( $this->id > 0 ) { $update = array(); $update['sender'] = $this->sender; $update['recipient'] = $this->recipient; $update['read'] = $this->read; $update['subject'] = $this->subject; $update['message'] = $this->message; $this->registry->getObject('db')->updateRecords( 'messages', $update, 'ID=' . $this->id ); } else { $insert = array(); $insert['sender'] = $this->sender; $insert['recipient'] = $this->recipient; $insert['read'] = $this->read; $insert['subject'] = $this->subject; $insert['message'] = $this->message; $this->registry->getObject('db')->insertRecords( 'messages', $insert ); $this->id = $this->registry->getObject('db')->lastInsertID(); } } One getter method that we need, is to return the user ID of the recipient, so we can check that the currently logged in user has permission to read the message: /** * Get the recipient of the message * @return int */ public function getRecipient() { return $this->recipient; } We should also provide a method to delete the message from the database, should the user wish to delete a message: /** * Delete the current message * @return boolean */ public function delete() { $sql = "DELETE FROM messages WHERE ID=" . $this->id; $this->registry->getObject('db')->executeQuery( $sql ); if( $this->registry->getObject('db')->affectedRows() > 0 ) { $this->id =0; return true; } else { return false; } } Finally, we have a toTags method, which converts all of the non-object and non-array variables into template tags, so when we create a view message method in the controller, we simply need to construct the message object and call the toTags method: /** * Convert the message data to template tags * @param String $prefix prefix for the template tags * @return void */ public function toTags( $prefix='' ) { foreach( $this as $field => $data ) { if( ! is_object( $data ) && ! is_array( $data ) ) { $this->registry->getObject('template')->getPage()->addTag( $prefix.$field, $data ); } } } } ?> Messages model Similar to how we have a model for representing a single relationship and another for representing a number of relationships, we also need a model to represent a number of messages within the site. This is to handle the lookup of a user's private message inbox. <?php /** * Messages model */ class Messages { /** * Messages constructor * @param Registry $registry * @return void */ public function __construct( Registry $registry ) { $this->registry = $registry; } /** * Get a users inbox * @param int $user the user * @return int the cache of messages */ public function getInbox( $user ) { $sql = "SELECT IF(m.read=0,'unread','read') as read_style, m.subject, m.ID, m.sender, m.recipient, DATE_FORMAT(m.sent, '%D %M %Y') as sent_friendly, psender.name as sender_name FROM messages m, profile psender WHERE psender.user_id=m.sender AND m.recipient=" . $user . " ORDER BY m.ID DESC"; $cache = $this->registry->getObject('db')->cacheQuery( $sql ); return $cache; } } ?>
Read more
  • 0
  • 1
  • 4738

article-image-microsoft-dynamics-nav-2009-creating-matrix-form
Packt
26 Oct 2010
5 min read
Save for later

Microsoft Dynamics NAV 2009: Creating a Matrix Form

Packt
26 Oct 2010
5 min read
  Microsoft Dynamics NAV 2009 Programming Cookbook Build better business applications with NAV Write NAV programs to do everything from finding data in a table to integration with an instant messenger client Develop your own .NET code to perform tasks that NAV cannot handle on its own Work with SQL Server to create better integration between NAV and other systems Learn to use the new features of the NAV 2009 Role Tailored Client Easy-to-read recipes with detailed explanations and images Maximize your learning with short tutorials that tell you exactly what you need to know without all of the fluff The reader would benefit by reading the previous article on Microsoft Dynamics NAV 2009: Designing Forms How to do it... Add a global function CalculateData that returns a text variable. Add a global function ColumnHeader that returns a text variable. Add a matrix box to the form. Set the following properties on the matrix box control: Set the following property on the form: Add the No. and Name fields to the left-hand side of the matrix box using the Field menu. Add a textbox to the right-hand side of the matrix box. Set the following property on the textbox: Add a textbox as a column header above that textbox. Set the following property on the textbox: Add the following code to the ColumnHeader function. EXIT(CurrForm.MatrixBox.MatrixRec."No."); Add the following local variables to the CalculateData function: Add the following code to the CalculateData function ItemLedgerEntry.RESET; ItemLedgerEntry.SETCURRENTKEY("Source Type", "Source No.", "Item No.", "Variant Code", "Posting Date"); ItemLedgerEntry.SETRANGE("Source Type", ItemLedgerEntry."Source Type"::Customer); ItemLedgerEntry.SETRANGE("Source No.", "No."); ItemLedgerEntry.SETRANGE("Item No.", CurrForm.MatrixBox.MatrixRec."No."); ItemLedgerEntry.SETRANGE("Entry Type", ItemLedgerEntry."Entry Type"::Sale); IF ItemLedgerEntry.FINDSET THEN REPEAT ItemLedgerEntry.CALCFIELDS("Sales Amount (Actual)"); TotalSales := TotalSales + ItemLedgerEntry."Sales Amount (Actual)"; UNTIL ItemLedgerEntry.NEXT = 0; EXIT(FORMAT(TotalSales)); After running the resulting form, you should see something similar to the following screenshot: How it works... A matrix form consists of two tables and some calculation based on those two tables. One set of records runs vertically along the left-hand side of the matrix box while the other set runs horizontally across the top. A grid is displayed on the rest of the form displaying a calculated value. We'll examine each of these pieces individually. We begin by creating a normal form that is bound to the Customer table. For this special form we add a matrix box control. The left-hand side operates exactly the same as a standard list form. It will display all of the customers and there will be a scrollbar to look through the list. As we don't want the user to change anything on this form, we set the Editable property of the matrix box to No. We will also have to write code that refers to this control so we must give it a name. Also, the matrix box itself operates on a table. In this case it is the Item table. As there is so much data stored in a table, we have to tell the control what we want to see. That's why we add a textbox as a column header to the top of the form. The source expression for that textbox is the ColumnHeader method. Let's take a look at the code there. EXIT(CurrForm.MatrixBox.MatrixRec."No."); CurrForm is the current form. MatrixBox is the value in the name property of our matrix box control. MatrixRec is the record in the matrix box that we are referring to (just like rec on a normal form). Finally, No. is the field from the MatrixSourceTable property(in this case the Item No). So our column headers will just be the Item Number from the Item table. Lastly, we have to tell the form how to calculate the data we want to see. We add another textbox to the form and give it a source expression of CalculateData, which is a function on our form. This function could return anything, but in our case it returns the amount a customer has spent on a specific item. Let's take a look at the important code that combines the data from both tables. ItemLedgerEntry.SETRANGE("Source No.", "No."); ItemLedgerEntry.SETRANGE("Item No.", CurrForm.MatrixBox.MatrixRec."No."); The Item Ledger Entry table already has fields that refer to the Customer table and to the Item table. The first filter uses the No. field from the source table (Customer). The second filter determines the current Item Number from the matrix box and uses it. Later in the function, a number is calculated and returned as a text variable. Summary In this part of the article series we covered: Creating a Matrix Form In the next part we will create a wizard-style form. Further resources on this subject: Microsoft Dynamics NAV 2009: Designing Forms Microsoft Dynamics NAV 2009: Creating a Wizard-style Form
Read more
  • 0
  • 0
  • 3911

article-image-microsoft-dynamics-nav-2009-creating-wizard-style-form
Packt
26 Oct 2010
4 min read
Save for later

Microsoft Dynamics NAV 2009: Creating a Wizard-style Form

Packt
26 Oct 2010
4 min read
Microsoft Dynamics NAV 2009 Programming Cookbook Build better business applications with NAV Write NAV programs to do everything from finding data in a table to integration with an instant messenger client Develop your own .NET code to perform tasks that NAV cannot handle on its own Work with SQL Server to create better integration between NAV and other systems Learn to use the new features of the NAV 2009 Role Tailored Client Easy-to-read recipes with detailed explanations and images Maximize your learning with short tutorials that tell you exactly what you need to know without all of the fluff How to do it... Add a frame to the form. Set the following properties on the textbox: Add a label to the frame with the caption "Frame 1". Set the following properties on the Label: Copy the frame and paste two copies of it on the form. Change the labels in the new frames to be Frame 2 and Frame 3. Change the Name properties of the frames to Frame2 and Frame3 respectively. Your form should look like the one shown in the following screenshot: Add four buttons to the form beneath Frame 1. The name and caption properties on each should be Back, Next, Finish, and Cancel respectively. Add the following code to the OnOpenForm trigger: CurrForm.Frame1.XPOS := 0; CurrForm.Frame1.YPOS := 0; CurrForm.Frame2.XPOS := 0; CurrForm.Frame2.YPOS := 0; CurrForm.Frame3.XPOS := 0; CurrForm.Frame3.YPOS := 0; CurrForm.HEIGHT := CurrForm.Cancel.YPOS + CurrForm.Cancel.HEIGHT + 220; CurrForm.WIDTH := CurrForm.Cancel.XPOS + CurrForm.Cancel.WIDTH + 220; WizardStep := 1; ShowStep(TRUE); Add a function named ShowStep that takes in a boolean value named Show as a parameter. Add the following code to the function: CASE WizardStep OF 1: BEGIN CurrForm.Frame1.VISIBLE := Show; CurrForm.Frame2.VISIBLE := NOT Show; CurrForm.Frame3.VISIBLE := NOT Show; CurrForm.Back.ENABLED := NOT Show; CurrForm.Next.ENABLED := Show; CurrForm.Finish.ENABLED := NOT Show; END; 2: BEGIN CurrForm.Frame1.VISIBLE := NOT Show; CurrForm.Frame2.VISIBLE := Show; CurrForm.Frame3.VISIBLE := NOT Show; CurrForm.Back.ENABLED := Show; CurrForm.Next.ENABLED := Show; CurrForm.Finish.ENABLED := NOT Show; END; 3: BEGIN CurrForm.Frame1.VISIBLE := NOT Show; CurrForm.Frame2.VISIBLE := NOT Show; CurrForm.Frame3.VISIBLE := Show; CurrForm.Back.ENABLED := Show; CurrForm.Next.ENABLED := NOT Show; CurrForm.Finish.ENABLED := Show; END; END; Add the following code to the OnPush trigger of the Back button: ShowStep(FALSE); WizardStep -= 1; ShowStep(TRUE); Add the following code to the OnPush trigger of the Next button: ShowStep(FALSE); WizardStep -= 1; ShowStep(TRUE); Add the following code to the OnPush trigger of the Finish button: CurrForm.CLOSE; Add the following code to the OnPush trigger of the Cancel button: CurrForm.CLOSE Save and close the form. How it works... The form contains three frames, only one of which is visible at any given time. In the design view, you can see that our form is quite wide and tall, but that would not look right when displaying a wizard form. That's why we place code in the OnOpenForm trigger. The first set of lines places all of the frames on top of each other. The middle set changes the width and height of the form. Finally, the third sets the appropriate frames to be visible or not and enables the correct buttons. Our custom method ShowStep decides what should be visible and what should not. It is just a large CASE statement based on the WizardStep variable. On the first frame for example, we can't move backwards to disable the Back button. We can't finish until we get to the last frame so that the Finish button is disabled until that point. On the Back and Next buttons we decrement and increment the WizardStep variable so that the ShowStep method knows what to do. Other than the initial opening of the form we always call the function with FALSE as a parameter to "undo" what is currently displayed, change the WizardStep variable, and call the function with parameter TRUE to display new information. Summary In this part of the article series we covered: Creating a Wizard-style Form In the next part we will cover Updating Parent and Subform. Further resources on this subject: Microsoft Dynamics NAV 2009: Designing Forms Microsoft Dynamics NAV 2009: Creating a Matrix Form
Read more
  • 0
  • 0
  • 1687

article-image-microsoft-wcf-hosting-and-configuration
Packt
25 Oct 2010
7 min read
Save for later

Microsoft WCF Hosting and Configuration

Packt
25 Oct 2010
7 min read
Service hosting and configuration is very important for building WCF services, especially at the service deployment stage. After developers complete the service development, we will need to deploy the service so as to make it available to all the client consumers. In the real world, there are various service deployment scenarios available, which will result in different deployment and configuration requirements on the service configuration or the hosting environment. As an enhanced service development platform, WCF provides rich, built-in support on service hosting and configuration that can fulfill most of the existing deployment demands and requirements. For example, the most popular IIS hosting approach can provide high availability and stable service for local intranet or public internet-based deployment cases. The Windows service-hosting approach makes WCF service hosting easier to integrate with existing background scheduled tasks, and the self-hosting approach provides the most flexibility and customization points for service deployment in a production environment. In this article, we will look at seven recipes on various WCF hosting and configuration scenarios. The recipes start with four typical hosting cases—self-hosting, Windows service hosting, IIS-based HTTP hosting, and IIS based non-HTTP hosting. This is followed by two customized service-hosting cases—including a custom ServiceHostFactory and a dedicated singleton-instance hosting. The last recipe demonstrates a more advanced WCF service-hosting scenario—Windows SharePoint Service hosting. Hosting a service in a console application When creating a simple demo program for .NET framework, we will probably choose a console application. At the same, when talking about WCF service hosting, the console-hosting scenario is the most convenient one, which is especially handy and useful when we want to do some quick demo or testing on some WCF functionality. How to do it... Create a .NET framework-based Console project through Visual Studio. Visual Studio provides various project templates for creating a .NET framework-based application. For our sample console-hosting service here, we will choose the Console Application project type from the Visual Studio New Project wizard. Add a new WCF service into the project. We can simply accomplish this by using the Add New Item function in Visual Studio and choose WCF Service as the item type from Visual Studio's Add New Item UI. Add code into the Main function to start up the WCF service. The following code shows the typical Main function that starts up a WCF service in a console application: static void Main(string[] args) { using (ServiceHost consoleHost = new ServiceHost(typeof(TestService))) { consoleHost.Open(); Console.WriteLine("press any key to stop service host..."); Console.ReadLine(); } } How it works... When you add a new WCF Service item in Visual Studio, the IDE actually helps you to finish the following three tasks: Creating a ServiceContract interface. Creating a Service class that implements the ServiceContract interface. The following code shows the sample ServiceContract and implementation class used in this recipe. [ServiceContract] public interface ITestService { [OperationContract] void DoWork(); } public class TestService : ITestService { public void DoWork() { } } Adding the service endpoint and binding configuration in the App.config file. In addition to the Contract and service type, the IDE will also insert a default configuration setting for the endpoint that can be exposed through the service. The following screenshot shows the sample service configuration section that contains a single endpoint, which uses WSHttpBinding. With the code and configuration entries as defined previously, we can start our service host by supplying the service type in the constructor of the ServiceHost class. using (ServiceHost consoleHost = new ServiceHost(typeof(TestService))) What the runtime will do is, it will lookup the configuration file and load the <service> entry that has the name identical to the type specified in the constructor, and launch the service and endpoints defined in it. The source code for this article can be found at http://www.packtpub.com/code_download/6034 Hosting a service in Windows Service Windows Services are widely used on Windows operating systems for hosting applications that will perform some long-run or scheduled tasks in the background. Applications hosted via Windows Service can be running under a specific user account and can choose the startup mode (manually or automatically). As a popular service-application-hosting scenario, it is also quite common to deploy a WCF service as a Windows Service. How to do it... In this recipe, we will use a typical .NET-based Windows Service to demonstrate how to host a WCF service in a Windows Service application. Let's go through the detailed steps: Create a Windows Service project. The first step is to create a new Windows Service project through the Visual Studio IDE. When creating the project, we simply choose the Windows Service project type. The following screenshot shows how we can select the Windows Service project type in the Visual Studio New Project wizard. Add a new WCF service item. As a WCF service hosting application, we certainly need to have a WCF service defined here. The steps for creating a WCF service are the same as what we've discussed in the Hosting a service in console application recipe. Add service hosting code into the service startup and shutdown event. As for the service-hosting code in the Windows Service, we need to put it in the correct place, since the .NET-based Windows Service type doesn't directly expose the Main function. The following code shows how the WCF service startup and shutdown code is defined: public partial class Service1 : ServiceBase { ServiceHost _svcHost = null; protected override void OnStart(string[] args) { // Start the service host here _svcHost = new ServiceHost(typeof(TestService)); _svcHost.Open(); } protected override void OnStop() { // Close the service host _svcHost.Close(); } } Add an installer for the Windows Service. Now the Windows Service class and WCF service types have been defined. However, we still need to add another component—the installer class for deploying the Windows Service into the Windows Service collection on the target operating system. In the Visual Studio IDE, we can simply add an installer type for the Windows Service by the context menu on the component designer. The following screenshot shows the context menu item for creating the installer class for the Windows Service. The IDE will help create two helper classes—one is of ServiceProcessInstaller type and another of ServiceInstaller type. We can specify many deployment parameters for the Windows Service in the Property panel of the two classes. The following screenshot shows the properties of the sample serviceProcessInstaller1 class. The next screenshot shows the properties of the sample serviceInstaller1 class. As with the screenshots displayed, Visual Studio will use standard Properties windows for displaying and configuring the individual properties of the Windows Service classes. Install the Windows Service through Installutil.exe. The last step is to install the Windows Service we have created (after building the project) into the operating system. This can be done by using the Installutil.exe tool provided by the .NET framework. You can directly execute the Installutil.exe command within the Visual Studio command-line prompt window or you can choose to launch the tool through its absolute path in the .NET framework folder such as C: WindowsMicrosoft.NETFrameworkv4.0.30319. The following statements show the complete commands for installing and uninstalling a .NET-based Windows Service application via the Installutil. exe tool. Install the Windows Service: InstallUtil.exe WCFNTService.exe Uninstall the Windows Service: Install Util.exe /u WCFNTService.exe The WCFNTService.exe mentioned earlier is the output assembly name of the sample Windows Service project. How it works... The OnStart event is fired when the Windows Service is starting, while the OnStop event is fired when the Windows Service is shutting down. Therefore, they are the best places for us to put the WCF service-hosting code. Sometimes, we may need to access some remote or protected resource in our Windows Service host program. In such cases, it is important to specify a proper service account, either at development time or in the Windows Service Configuration Manager. The following screenshot shows the service list, which contains the installed sample Windows Service in Windows Service Configuration Manager.
Read more
  • 0
  • 0
  • 2951
article-image-backup-postgresql-9
Packt
25 Oct 2010
11 min read
Save for later

Backup in PostgreSQL 9

Packt
25 Oct 2010
11 min read
Most people admit that backups are essential, though they also devote only a very small amount of time to thinking about the topic. The first recipe is about understanding and controlling crash recovery. We need to understand what happens if the database server crashes, so we can understand when we might need to recover. The next recipe is all about planning. That's really the best place to start before you go charging ahead to do backups. Understanding and controlling crash recovery Crash recovery is the PostgreSQL subsystem that saves us if the server should crash, or fail as a part of a system crash. It's good to understand a little about it and to do what we can to control it in our favor. How to do it... If PostgreSQL crashes there will be a message in the server log with severity-level PANIC. PostgreSQL will immediately restart and attempt to recover using the transaction log or Write Ahead Log (WAL). The WAL consists of a series of files written to the pg_xlog subdirectory of the PostgreSQL data directory. Each change made to the database is recorded first in WAL, hence the name "write-ahead" log. When a transaction commits, the default and safe behavior is to force the WAL records to disk. If PostgreSQL should crash, the WAL will be replayed, which returns the database to the point of the last committed transaction, and thus ensures the durability of any database changes. Note that the database changes themselves aren't written to disk at transaction commit. Those changes are written to disk sometime later by the "background writer" on a well-tuned server. Crash recovery replays the WAL, though from what point does it start to recover? Recovery starts from points in the WAL known as "checkpoints". The duration of crash recovery depends upon the number of changes in the transaction log since the last checkpoint. A checkpoint is a known safe starting point for recovery, since at that time we write all currently outstanding database changes to disk. A checkpoint can become a performance bottleneck on busy database servers because of the number of writes required. There are a number of ways of tuning that, though please also understand the effect on crash recovery that those tuning options may cause. Two parameters control the amount of WAL that can be written before the next checkpoint. The first is checkpoint_segments, which controls the number of 16 MB files that will be written before a checkpoint is triggered. The second is time-based, known as checkpoint_timeout, and is the number of seconds until the next checkpoint. A checkpoint is called whenever either of those two limits is reached. It's tempting to banish checkpoints as much as possible by setting the following parameters: checkpoint_segments = 1000 checkpoint_timeout = 3600 Though if you do you might give some thought to how long the recovery will be if you do and whether you want that. Also, you should make sure that the pg_xlog directory is mounted on disks with enough disk space for at least 3 x 16 MB x checkpoint_segments. Put another way, you need at least 32 GB of disk space for checkpoint_segments = 1000. If wal_keep_segments > 0 then the server can also use up to 16MB x (wal_keep_segments + checkpoint_segments). How it works... Recovery continues until the end of the transaction log. We are writing this continually, so there is no defined end point; it is literally the last correct record. Each WAL record is individually CRC checked, so we know whether a record is complete and valid before trying to process it. Each record contains a pointer to the previous record, so we can tell that the record forms a valid link in the chain of actions recorded in WAL. As a result of that, recovery always ends with some kind of error reading the next WAL record. That is normal. Recovery performance can be very fast, though it does depend upon the actions being recovered. The best way to test recovery performance is to setup a standby replication server. There's more... It's possible for a problem to be caused replaying the transaction log, and for the database server to fail to start. Some people's response to this is to use a utility named pg_resetxlog, which removes the current transaction log files and tidies up after that surgery has taken place. pg_resetxlog destroys data changes and that means data loss. If you do decide to run that utility, make sure you take a backup of the pg_xlog directory first. My advice is to seek immediate assistance rather than do this. You don't know for certain that doing this will fix a problem, though once you've done it, you will have difficulty going backwards. Planning backups This section is all about thinking ahead and planning. If you're reading this section before you take a backup, well done. The key thing to understand is that you should plan your recovery, not your backup. The type of backup you take influences the type of recovery that is possible, so you must give some thought to what you are trying to achieve beforehand. If you want to plan your recovery, then you need to consider the different types of failures that can occur. What type of recovery do you wish to perform? You need to consider the following main aspects: Full/Partial database? Everything or just object definitions only? Point In Time Recovery Restore performance We need to look at the characteristics of the utilities to understand what our backup and recovery options are. It's often beneficial to have multiple types of backup to cover the different types of failure possible. Your main backup options are logical backup—using pg_dump physical backup—file system backup pg_dump comes in two main flavors: pg_dump and pg_dumpall. pg_dump has a -F option to produce backups in various file formats. The file format is very important when it comes to restoring from backup, so you need to pay close attention to that. The following table shows the features available, depending upon the backup technique selected. Table of Backup/Recovery options: SQL dump to an archive file pg_dump -F cSQL dump to a script file pg_dump -F p or pg_dumpallFilesystem backup using pg_start_ backupBackup typeLogicalLogicalPhysicalRecover to point in time?NoNoYesBackup all databases?One at a timeYes (pg_dumpall)YesAll databases backed up at same time?NoNoYesSelective backup?YesYesNo (Note 3)Incremental backup?NoNoPossible (Note 4)Selective restore?YesPossible (Note 1)No (Note 5)DROP TABLE recoveryYes Yes Possible (Note 6) DROP TABLESPACE recovery Possible (Note 2)Possible (Note 6)Possible (Note 6)Compressed backup files?YesYesYesBackup is multiple files?NoNoYesParallel backup possible?NoNoYesParallel restore possible?YesNoYesRestore to later release?YesYesNoStandalone backup?YesYesYes (Note 7)Allows DDL during backupNoNoYes How to do it... If you've generated a script with pg_dump or pg_dumpall and need to restore just a single object, then you're going to need to go deep. You will need to write a Perl script (or similar) to read the file and extract out the parts you want. It's messy and time-consuming, but probably faster than restoring the whole thing to a second server, and then extracting just the parts you need with another pg_dump. See recipe Recovery of a dropped/damaged tablespace. Selective backup with physical backup is possible, though will cause later problems when you try to restore. Selective restore with physical backup isn't possible with currently supplied utilities. See recipe for Standalone hot physical backup How it works... To backup all databases, you may be told you need to use the pg_dumpall utility. I have four reasons why you shouldn't do that, which are as follows: If you use pg_dumpall, then the only output produced is into a script file. Script files can't use the parallel restore feature of pg_restore, so by taking your backup in this way you will be forcing the restore to be slower than it needs to be. pg_dumpall produces dumps of each database, one after another. This means that: pg_dumpall is slower than running multiple pg_dump tasks in parallel, one against each database. The dumps of individual databases are not consistent to a particular point in time. If you start the dump at 04:00 and it ends at 07:00 then we're not sure exactly when the dump relates to—sometime between 0400 and 07:00. Options for pg_dumpall are similar in many ways to pg_dump, though not all of them exist, so some things aren't possible. In summary, pg_dumpall is slower to backup, slow to restore, and gives you less control over the dump. I suggest you don't use it for those reasons. If you have multiple databases, then I suggest you take your backup by doing either. Dump global information for the database server using pg_dumpall -g. Then dump all databases in parallel using a separate pg_dump for each database, taking care to check for errors if they occur. Use the physical database backup technique instead. Hot logical backup of one database Logical backup makes a copy of the data in the database by dumping out the contents of each table. How to do it... The command to do this is simple and as follows: pg_dump -F c > dumpfile or pg_dump -F c –f dumpfile You can also do this through pgAdmin3 as shown in the following screenshot: How it works... pg_dump produces a single output file. The output file can use the split(1) command to separate the file into multiple pieces if required. pg_dump into the custom format is lightly compressed by default. Compression can be removed or made more aggressive. pg_dump runs by executing SQL statements against the database to unload data. When PostgreSQL runs an SQL statement we take a "snapshot" of currently running transactions, which freezes our viewpoint of the database. We can't (yet) share that snapshot across multiple sessions, so we cannot run an exactly consistent pg_dump in parallel in one database, nor across many databases. The time of the snapshot is the only time we can recover to—we can't recover to a time either before or after that time. Note that the snapshot time is the start of the backup, not the end. When pg_dump runs, it holds the very lowest kind of lock on the tables being dumped. Those are designed to prevent DDL from running against the tables while the dump takes place. If a dump is run at the point that other DDL are already running, then the dump will sit and wait. If you want to limit the waiting time you can do that by setting the –-lock-wait-timeout option. pg_dump allows you to make a selective backup of tables. The -t option also allows you to specify views and sequences. There's no way to dump other object types individually using pg_dump. You can use some supplied functions to extract individual snippets of information available at the following website: https://www.postgresql.org/docs/9.0/static/functions-info.html#FUNCTIONS-INFO-CATALOG-TABLE pg_dump works against earlier releases of PostgreSQL, so it can be used to migrate data between releases. pg_dump doesn't generally handle included modules very well. pg_dump isn't aware of additional tables that have been installed as part of an additional package, such as PostGIS or Slony, so it will dump those objects as well. That can cause difficulties if you then try to restore from the backup, as the additional tables may have been created as part of the software installation process in an empty server. There's more... What time was the pg_dump taken? The snapshot for a pg_dump is taken at the beginning of a run. The file modification time will tell you when the dump finished. The dump is consistent at the time of the snapshot, so you may want to know that time. If you are making a script dump, you can do a dump verbose as follows: pg_dump -v which then adds the time to the top of the script. Custom dumps store the start time as well and that can be accessed using the following: pg_restore --schema-only -v dumpfile | head | grep Started -- Started on 2010-06-03 09:05:46 BST See also Note that pg_dump does not dump the roles (such as users/groups) and tablespaces. Those two things are only dumped by pg_dumpall; see the next recipes for more detailed descriptions.
Read more
  • 0
  • 0
  • 3214

article-image-recovery-postgresql-9
Packt
25 Oct 2010
14 min read
Save for later

Recovery in PostgreSQL 9

Packt
25 Oct 2010
14 min read
Recovery of all databases Recovery of a complete database server, including all of its databases, is an important feature. This recipe covers how to do that in the simplest way possible. Getting ready Find a suitable server on which to perform the restore. Before you recover onto a live server, always take another backup. Whatever problem you thought you had could be just about to get worse. How to do it... LOGICAL (from custom dump -F c): Restore of all databases means simply restoring each individual database from each dump you took. Confirm you have the correct backup before you restore: pg_restore --schema-only -v dumpfile | head | grep Started Reload globals from script file as follows: psql -f myglobals.sql Reload all databases. Create the databases using parallel tasks to speed things along. This can be executed remotely without needing to transfer dumpfile between systems. Note that there is a separate dumpfile for each database. pg_restore -d postgres -j 4 dumpfile LOGICAL (from script dump created by pg_dump –F p): As above, though with this command to execute the script. This can be executed remotely without needing to transfer dumpfile between systems. Confirm you have the correct backup before you restore. If the following command returns nothing, then the file is not timestamped, and you'll have to identify it in a different way: head myscriptdump.sql | grep Started Reload globals from script file as follows: psql -f myglobals.sql Reload all scripts like the following: psql -f myscriptdump.sql LOGICAL (from script dump created by pg_dumpall): We need to follow the procedure, which is shown next. Confirm you have the correct backup before you restore. If the following command returns nothing, then the file is not timestamped, and you'll have to identify it in a different way: head myscriptdump.sql | grep Started Find a suitable server, or create a new virtual server. Reload script in full psql -f myscriptdump.sql PHYSICAL: Restore the backup file onto the target server. Extract the backup file into the new data directory. Confirm that you have the correct backup before you restore. $ cat backup_label START WAL LOCATION: 0/12000020 (file 000000010000000000000012) CHECKPOINT LOCATION: 0/12000058 START TIME: 2010-06-03 19:53:23 BST LABEL: standalone Check all file permissions and ownerships are correct and links are valid. That should already be the case if you are using the postgres userid everywhere, which is recommended. Start the server That procedure is so simple. That also helps us understand that we need both a base backup and the appropriate WAL files. If you used other techniques, then we need to step through the tasks to make sure we cover everything required as follows: Shutdown any server running in the data directory. Restore the backup so that any files in the data directory that have matching names are replaced with the version from the backup. (The manual says delete all files and then restore backup—that might be a lot slower than running an rsync between your backup and the destination without the –-update option). Remember that this step can be performed in parallel to speed things up, though it is up to you to script that. Check that all file permissions and ownerships are correct and links are valid. That should already be the case if you are using the postgres userid everywhere, which is recommended. Remove any files in pg_xlog/. Copy in any latest WAL files from a running server, if any. Add in a recovery.conf and set its file permissions correctly also. Start the server. The only part that requires some thought and checking is which parameters you select for the recovery.conf. There's only one that matters here, and that is the restore_command. restore_command tells us how to restore archived WAL files. It needs to be the command that will be executed to bring back WAL files from the archive. If you are forward-thinking, there'll be a README.backup file for you to read to find out how to set the restore_command. If not, then presumably you've got the location of the WAL files you've been saving written down somewhere. Say, for example, that your files are being saved to a directory named /backups/pg/servername/archive, owned by the postgres user. On a remote server named backup1, we would then write this all on one line of the recovery.conf as follows: restore_command = 'scp backup1:/backups/pg/servername/archive/%f %p' How it works... PostgreSQL is designed to require very minimal information to perform a recovery. We try hard to wrap all the details up for you. Logical recovery: Logical recovery executes SQL to re-create the database objects. If performance is an issue, look at the recipe on recovery performance. Physical recovery: Physical recovery re-applies data changes at the block level so tends to be much faster than logical recovery. Physical recovery requires both a base backup and a set of archived WAL files. There is a file named backup_label in the data directory of the base backup. This tells us to retrieve a .backup file from the archive that contains the start and stop WAL locations of the base backup. Recovery then starts to apply changes from the starting WAL location, and must proceed as far as the stop address for the backup to be valid. After recovery completes, the recovery.conf file is renamed to recovery.done to prevent the server from re-entering recovery. The server log records each WAL file restored from the archive, so you can check progress and rate of recovery. You can query the archive to find out the name of the latest archived WAL file to allow you to calculate how many files to go. The restore_command should return 0 if a file has been restored and non-zero for failure cases. Recovery will proceed until there is no next WAL file, so there will eventually be an error recorded in the logs. If you have lost some of the WAL files, or they are damaged, then recovery will stop at that point. No further changes after that will be applied, and you will likely lose those changes; that would be the time to call your support vendor. There's more... You can start and stop the server once recovery has started without any problem. It will not interfere with the recovery. You can connect to the database server while it is recovering and run queries, if that is useful. That is known as Hot Standby mode. Recovery to a point in time If your database suffers a problem at 15:22 p.m. and yet your backup was taken at 04:00 a.m. you're probably hoping there is a way to recover the changes made between those two times. What you need is known as "point-in-time recovery". Regrettably, if you've made a backup with pg_dump at 04:00 a.m. then you won't be able to recover to any other time than 04:00. As a result, the term point-in-time recovery (PITR) has become synonymous with the physical backup and restore technique in PostgreSQL. Getting ready If you have a backup made with pg_dump, then give up all hope of using that as a starting point for a point in time recovery. It's a frequently asked question, but the answer is still "no"; the reason it gets asked is exactly why I'm pleading with you to plan your backups ahead of time. First, you need to decide what the point of time is that to which you would like to recover. If the answer is "as late as possible", then you don't need to do a PITR at all, just recover until end of logs. How to do it... How do you decide to what point to recover? The point where we stop recovery is known as the "recovery target". The most straightforward way is to do this based upon a timestamp. In the recovery.conf, you can add (or uncomment) a line that says the following: recovery_target_time = '2010-06-01 16:59:14.27452+01' or similar. Note that you need to be careful to specify the time zone of the target, so that it matches the time zone of the server that wrote the log. That might differ from the time zone of the current server, so check. After that, you can check progress during a recovery by running queries in Hot Standby mode. How it works... Recovery works by applying individual WAL records. These correspond to individual block changes, so there are many WAL records to each transaction. The final part of any successful transaction is a commit WAL record, though there are abort records as well. Each transaction completion record has a timestamp on it that allows us to decide whether to stop at that point or not. You can also define a recovery target using a transaction id (xid), though finding out which xid to use is somewhat difficult, and you may need to refer to external records if they exist. The recovery target is specified in the recovery.conf and cannot change while the server is running. If you want to change the recovery target, you can shutdown the server, edit the recovery.conf, and then restart the server. Be careful though, if you change the recovery target and recovery is already passed the point, it can lead to errors. If you define a recovery_target_timestamp that has already passed, then recovery will stop almost immediately, though this will be later than the correct stopping point. If you define a recovery_target_xid that has already passed, then recovery will just continue to the end of logs. Restarting recovery from the beginning using a fresh restore of the base backup is always safe. Once a server completes recovery, it will assign a new "timeline". Once a server is fully available, we can write new changes to the database. Those changes might differ from changes we made in a previous "future history" of the database. So we differentiate between alternate futures using different timelines. If we need to go back and run recovery again, we can create a new server history using the original or subsequent timelines. The best way to think about this is that it is exactly like a Sci-Fi novel—you can't change the past but you can return to an earlier time and take a different action instead. But you'll need to be careful not to confuse yourself. There's more... pg_dump cannot be used as a base backup for a PITR. The reason is that a log replay contains the physical changes to data blocks, not logical changes based upon Primary Keys. If you reload a pg_dump the data will likely go back into different data blocks, so the changes wouldn't correctly reference the data. WAL doesn't contain enough information to reconstruct all SQL fully that produced those changes. Later feature additions to PostgreSQL may add the required information to WAL. See also Planned in 9.1 is the ability to pause/resume/stop recovery, and to set recovery targets while the server is up dynamically. This will allow you to use the Hot Standby facility to locate the correct stopping point more easily. You can trick Hot Standby into stopping recovery, which may help. Recovery of a dropped/damaged table You may drop or even damage a table in some way. Tables could be damaged for physical reasons, such as disk corruption, or they could also be damaged by running poorly specified UPDATEs/DELETEs, which update too many rows or overwrite critical data. It's a common request to recover from this situation from a backup. How to do it... The methods differ, depending upon the type of backup you have available. If you have multiple types of backup, you have a choice. LOGICAL (from custom dump -F c): If you've taken a logical backup using pg_dump into a custom file, then you can simply extract the table you want from the dumpfile like the following: pg_restore -t mydroppedtable dumpfile | psql or connect direct to the database using –d. The preceding command tries to re-create the table and then load data into it. Note that pg_restore -t option does not dump out any of the indexes on the table selected. That means we need a slightly more complex procedure than it would first appear, and the procedure needs to vary depending upon whether we are repairing a damaged table or putting back a dropped table. To repair a damaged table we want to replace the data in the table in a single transaction. There isn't a specific option to do this, so we need to do the following: Dump the table to a script file as follows: pg_restore -t mydroppedtable dumpfile > mydroppedtable.sql Edit a script named restore_mydroppedtable.sql with the following code: BEGIN; TRUNCATE mydroppedtable; i mydroppedtable.sql COMMIT; Then, run it using the following: psql -f restore_mydroppedtable.sql If you've dropped a table then you need to: Create a new database in which to work, name it restorework, as follows: CREATE DATABASE restorework; Restore the complete schema to the new database as follows: pg_restore --schema-only -d restorework dumpfile Now, dump just the definitions of the dropped table into a new file, which will contain CREATE TABLE, indexes, other constraints and grants. Note that this database has no data in it, so specifying –-schema-only is optional, as follows: pg_dump -t mydroppedtable --schema-only restorework > mydroppedtable.sql Now, recreate the table on the main database as follows: psql -f mydroppedtable.sql Now, reload just the data into database maindb as follows pg_restore -t mydroppedtable --data-only -d maindb dumpfile If you've got a very large table, then the fourth step can be a problem, because it builds the indexes as well. If you want you can manually edit the script into two pieces, one before the load ("pre-load") and one after the load ("post-load"). There are some ideas for that at the end of the recipe. LOGICAL (from script dump): The easy way to restore a single table from a script is as follows: Find a suitable server, or create a new virtual server. Reload the script in full, as follows: psql -f myscriptdump.sql From the recovered database server, dump the table, its data, and all the definitions of the dropped table into a new file as follows: pg_dump -t mydroppedtable -F c mydatabase > dumpfile Now, recreate the table into the original server and database, using parallel tasks to speed things along. This can be executed remotely without needing to transfer dumpfile between systems. pg_restore -d mydatabase -j 2 dumpfile The only way to extract a single table from a script dump without doing all of the preceding is to write a custom Perl script to read and extract just the parts of the file you want. That can be complicated, because you may need certain SET commands at the top of the file, the table, and data in the middle of the file, and the indexes and constraints on the table are near the end of the file. It's complex; the safe route is the one already mentioned. PHYSICAL: To recover a single table from a physical backup, we need to: Find a suitable server, or create a new virtual server. Recover the database server in full, as described in previous recipes on physical recovery, including all databases and all tables. You may wish to stop at a useful point in time. From the recovered database server, dump the table, its data, and all the definitions of the dropped table into a new file as follows: pg_dump -t mydroppedtable -F c mydatabase > dumpfile Now, recreate the table into the original server and database using parallel tasks to speed things along. This can be executed remotely without needing to transfer dumpfile between systems as follows: pg_restore -d mydatabase -j 2 dumpfile How it works... At present, there's no way to restore a single table from a physical restore in just a single step. See also Splitting a pg_dump into multiple sections, "pre" and "post" was proposed by me for an earlier release of PostgreSQL, though I haven't had time to complete that yet. It's possible to do that using an external utility also; the best script I've seen to split a dump file into two pieces is available at the following website: http://bucardo.org/wiki/split_postgres_dump
Read more
  • 0
  • 0
  • 5403

article-image-omnigraffle-5-shape-selection-re-styling-and-color-picker-detail
Packt
25 Oct 2010
8 min read
Save for later

OmniGraffle 5: Shape Selection, Re-Styling and Color Picker in Detail

Packt
25 Oct 2010
8 min read
OmniGraffle 5 Diagramming Essentials Create better diagrams with less effort using OmniGraffle Produce high-quality professional-looking diagrams that communicate information much better than words Makes diagramming fun and simple for Macintosh users Master the art of illustrating your ideas with OmniGraffle Learn to draw engaging charts and graphs to grasp your viewers' attention to your presentations A hands-on guide filled with visual step-by-step examples that cover both the basics and the advanced features of OmniGraffle        Easy shape selection When diagrams become complex and you want to change the appearance of many of the same objects, you can either hold down the shift key on your keyboard and select the shapes you need to change, or you can use the built-in selection functions in OmniGraffle. There are three built in methods of selecting shapes: The Edit | Select | Similar Objects menu command. The context sensitive menu when right-clicking on selected shapes (Select | Similar Objects). Using the Canvas: Selection inspector. If shapes are connected to each other, it's also possible to select connected shapes from the application menu or the context sensitive menu. You will deal with connected shapes later. What OmniGraffle defines as similar shapes Similar shapes are shapes that have exactly the same styling, not the form, type or size of the shapes. The styling can be; the fi lling color or blend of the shape, the stroke thickness, the corner radius, the stroke color, the shadow, if the shape is filled with a picture and if the shape has an associated text. Neither the size of two or more shapes, nor the content of the text will make OmniGraffle define the shapes as dissimilar. If you change the font type, weight or color–then OmniGraffle will define the shapes as dissimilar. As the few examples in the table below show more often than not, shapes that are of the same type (rectangle, circle, and so on) are dissimilar. ShapesExplanationResultSame font, color and weight, but different text.Similar shapes.Difference in the fuzziness of the shadow.Dissimilar shapes.Different font size.Dissimilar shapes.Different color. Different text, but same font, color and weight.Dissimilar shapes. Let's explore how easy it is to select similar shapes. Create an OmniGraffle document with only 4 shapes: Rectangle, Circle, Diamond, and Triangle. Mix them all together so it's not easy to manually select various shapes. In the download bundle, Ch:7, there is a file named Experiments in shape selections.graffle—you can open this if you do not want to create your own version. In the Canvas: Selection inspector (seen in the previous screenshot), you will see the four different shapes. Under each shape, there are two numbers separated by a forward slash (/). The number on the left indicates how many of the given shape are selected, and the number to the right of the slash is the total count of shapes on the current canvas. As you can see in the Selection inspector, we have 11 rectangles, 9 triangles, 10 circles, and 10 diamonds. To select all the diamonds on the canvas, click on the diamond shape in the Selection inspector. Notice that the numbers below the shape are now reading 10/10. If you click on the Fill style inspector and use the color named Honeydew from the Crayon color palette—all the diamonds change into this color. Now, click on the rectangle in the upper-left corner and right-click to get the context sensitive menu. Then select then use the Select | Similar Objects menu command, as seen next: Now all the rectangles are selected. Fill the rectangles with the color named Tin from the Crayons color palette. The next thing you are going to do is to select four of the circles and fill these with a yellow color. Notice that the Selection inspector now has five different shapes: You can now continue on your own to experiment changing various style properties to the shape groups. Selecting connected shapes You are now going to perform some experiments with connected shapes. Start with a diagram like the one next. You can either create this by hand, or you can open the file named Experiments in shape selections.graffle found in the Ch:7 directory in the download bundle. The diagram is found on the second canvas. Notice that all shapes are connected to each other. If you look at the Selection inspector, you'll see four shapes, where the lines are one of those shapes. OmniGraffle defines descendants to a selected shape as all shapes that are either connected to the right of or below the selected shape. OmniGraffle defines ancestors to a selected shape as all shapes that are either connected to the left of or above the selected shape. The following table lists a few actions and their corresponding results while working with connected shapes. ActionResultChoose (select) circle number 1 and execute Descendants from the Edit | Selection menu. This action results in the selection of the shapes connected below and to the right of the chosen shape.Select circle number 2 and choose Ancestors from the Edit | Selection menu. This action results in the selection of shapes connected to the left of the chosen shape.Select circle number 3 and choose Ancestors from the Edit | Selection menu. This action results in the selection of shapes connected above and to the left of the chosen shape.Select square B and choose Descendants from the Edit | Selection menu. This action result in every shape except circle number 1 and square A being selected.Select square C and choose Ancestors from the Edit | Selection menu. The shapes connected to the left of the chosen shape are selected.Select square C and choose Descendants from the Edit | Selection menu. The shapes connected below and to the right of the chosen shape are selected.Select any shape and choose Connected Objects from the Edit | Selection menu. This action results in the whole diagram being selected since every shape is connect to every other shape, either directly or indirectly. Selecting all these shapes—either by form or by connections seems like a very powerful tool, and indeed it is. With this way of selecting shapes, you can easily change the look and feel in a consistent manner throughout your whole diagram. Easy re-styling of shapes Instead of selecting similar shapes, and then changing their appearance by using the style inspectors, you can also drag and drop styles from the Style Tray directly onto the Selection inspector. Start your experiments in the easy re-styling of shapes by creating various shapes, and fill some of these with various colors. To save you some time and get right into the experimentation, you can also open the file named Experiments in re-styling shapes.graffle, which is found in the Ch: 6 folder of the download bundle. We're not quite happy with only having four yellow circles. Your first task is to make the rest of the circles yellow. Unfortunately, you do not know which yellow color these circles are – you could work with the color picker to get the right yellow. This is too much work. Let's do this the simple way. In the Selection inspector, you will see all the different shapes, including the four yellow circles. If you use the file from the download bundle, you should have the yellow circles as the first shape in the inspector. To select all the yellow circles, you could click on one of the circles and then use the Edit | Select | Similar Objects menu command. This is too much work really. Just click on the shape inside the inspector. What happens now is that all the yellow circles have been selected. In the Style Tray, the styling for these shapes is now shown: You can now drag the color chit (//Image 43) on to the white circle in the Selection inspector. Suddenly all your circles have this shade of yellow. And it's not only the color we can change in a second like this. In fact, your next job is to eradicate all of those gray and boring squares and instead replace these with the green and happy diamonds. This is also just a two-step process. Start by clicking on one of the diamonds in your canvas. Now, drag the Complete Style Chit (the leftmost of all the chits) onto the gray squares inside the selection inspector. Not only does this change the color of the square shapes— but it also changes the shapes into diamonds. You can thus drag any chit from the Style Tray onto any shapes both on the canvas , and also onto the Selection inspector. This is a very powerful tool to aid you in getting a consistent look for your shapes. You can also use this method to search and replace a lot of shapes in one go. No need to manually hunt around on a shape-by-shape basis.
Read more
  • 0
  • 0
  • 5510
article-image-introduction-postgresql-9
Packt
25 Oct 2010
12 min read
Save for later

Introduction to PostgreSQL 9

Packt
25 Oct 2010
12 min read
PostgreSQL 9 Admin Cookbook Over 80 recipes to help you run an efficient PostgreSQL 9.0 database Administer and maintain a healthy database Monitor your database ensuring that it performs as quickly as possible Tips for backup and recovery of your database Introduction PostgreSQL is a feature-rich general purpose database management system. It's a complex piece of software, but every journey begins with the first step. We start with your first connection. Many people fall at the first hurdle, so we try not to skip too swiftly past that. We move on quickly to enabling remote users, and from there to access through GUI administration tools. We also introduce the psql query tool, which is the tool used for loading our sample database. Introducing PostgreSQL 9 PostgreSQL is an advanced SQL database server, available on a wide range of platforms. One of the clearest benefits of PostgreSQL is that it is open source, meaning that you have a very permissive license to install, use, and distribute PostgreSQL without paying anyone fees or royalties. On top of that, PostgreSQL is well-known as a database that stays up for long periods, and requires little or no maintenance in many cases. Overall, PostgreSQL provides a very low total cost of ownership. PostgreSQL is also noted for its huge range of advanced features, developed over the course of more than 20 years continuous development and enhancement. Originally developed by the Database Research group at the University of California, Berkeley, PostgreSQL is now developed and maintained by a huge army of developers and contributors. Many of those contributors have full-time jobs related to PostgreSQL, working as designers, developers, database administrators, and trainers. Some, but not many, of those contributors work for companies that specialize in services for PostgreSQL, such as Hannu and me. No single company owns PostgreSQL, nor are you required, or even encouraged, to register your usage. PostgreSQL has the following main features: Excellent SQL Standards compliance up to SQL 2008 Client-server architecture Highly concurrent design where readers and writers don't block each other Highly configurable and extensible for many types of application Excellent scalability and performance with extensive tuning features What makes PostgreSQL different? The PostgreSQL project focuses on the following objectives: Robust, high-quality software with maintainable, well-commented code Low maintenance administration for both embedded and enterprise use Standards-compliant SQL, interoperability, and compatibility Performance, security, and high availability What surprises many people is that PostgreSQL's feature set is more comparable with Oracle or SQL Server than it is with MySQL. The only connection between MySQL and PostgreSQL is that those two projects are open source; apart from that, the features and philosophies are almost totally different. One of the key features of Oracle since Oracle 7 has been "snapshot isolation", where readers don't block writers, and writers don't block readers. You may be surprised to learn that PostgreSQL was the first database to be designed with this feature, and offers a full and complete implementation. PostgreSQL names this Multi-Version Concurrency Control (MVCC). PostgreSQL is a general-purpose database management system. You defi ne the database that you would like to manage with it. PostgreSQL offers you many ways to work. You can use a "normalized database model", you can utilize extensions such as arrays and record subtypes, or you can use a fully dynamic schema using an extension named hstore . PostgreSQL also allows you to create your own server-side functions in one of a dozen different languages. PostgreSQL is highly extensible, so you can add your own datatypes, operators, index types, and functional languages. For example, you can override different parts of the system using plugins to alter the execution of commands or add a new optimizer. All of these features offer a huge range of implementation options to software architects. There are many ways out of trouble when building applications and maintaining them over long periods of time. In the early days, when PostgreSQL was still a research database, the focus was solely on cool new features. Over the last 15 years, enormous amounts of code have been rewritten and improved, giving us one of the most stable, large, software servers available for operational use. You may also read that PostgreSQL was, or is, slower than My Favorite DBMS, whichever one that is. It's been a personal mission of mine over the last six years to improve server performance and the team have been successful in making the server highly performant and very scalable. That gives PostgreSQL enormous headroom for growth. Who is using PostgreSQL? Prominent users include Apple, BASF, Genentech, IMDB.com, Skype, NTT, Yahoo, and The National Weather Service. PostgreSQL receives well in excess of 1 million downloads per year, according to data submitted to the European Commission, who concluded "...PostgreSQL, is considered by many database users to be a credible alternative... We need to mention one last thing. When PostgreSQL was fi rst developed, it was named Postgres, and so many aspects of the project still refer to the word "postgres". For example, the default database is named postgres, and the software is frequently installed using the postgres userid. As a result, people shorten the name PostgreSQL to simply Postgres, and in many cases people use the two names interchangeably. PostgreSQL is pronounced as "post-grez-q-l". Postgres is pronounced as "post-grez". Some people get confused, and refer to "Postgre", which is hard to say, and likely to confuse people. Two names are enough, so please don't use a third name! Getting PostgreSQL PostgreSQL is 100% open source software. PostgreSQL is freely available to use, alter, or redistribute in any way you choose. PostgreSQL's license is an approved open source license very similar to the BSD (Berkeley Distribution Software) license, though only just different enough that it is now known as TPL (The PostgreSQL License). How to do it... PostgreSQL is already in use by many different application packages, and so you may already find it installed on your servers. Many Linux distributions include PostgreSQL as part of the basic installation, or include it with the installation disk. One thing to be wary of is that the version of PostgreSQL included may not be the latest release. It will typically be the latest major release that was available when that operating system release was published. There is usually no good reason to stick at that level—there is no increased stability implied there and later production versions are just as well-supported by the various Linux distributions. If you don't yet have a copy, or you don't have the latest version, you can download the source code or download binary packages for a wide variety of operating systems from the following URL: http://www.postgresql.org/download/ Installation details vary significantly from platform-to-platform and there aren't any special tricks or recipes to mention. Please, just follow the installation guide, and away you go. We've consciously avoided describing the installation processes here to make sure we don't garble or override the information published to assist you. If you would like to receive e-mail updates of the latest news, then you can subscribe to the PostgreSQL announce mailing list, which contains updates from all the vendors that support PostgreSQL. You'll get a few e-mails each month about new releases of core PostgreSQL and related software, conferences, and user group information. It's worth keeping in touch with developments. For more information about the PostgreSQL announce mailing list, visit the following URL: http://archives.postgresql.org/pgsql-announce/ How it works... Many people ask questions, such as "How can this be free?", "Are you sure I don't have to pay someone?", or "Who gives this stuff away for nothing?" Open source applications such as PostgreSQL work on a community basis, where many contributors perform tasks that make the whole process work. For many of those people, their involvement is professional, rather a hobby, and they can do this because there is generally a great value for both contributors and their employers alike. You might not believe it. You don't have to because It Just Works. There's more... Remember that PostgreSQL is more than just the core software. There is a huge range of websites offering add-ons, extensions, and tools for PostgreSQL. You'll also fi nd an army of bloggers describing useful tricks and discoveries that will help you in your work.   And, there is a range of professional companies able to offer you help when you need it. Connecting to PostgreSQL server How do we access PostgreSQL? Connecting to the database is most people's first experience of PostgreSQL, so we want to make it a good one. So, let's do it, and fix any problems we have along the way. Remember that a connection needs to be made securely, so there may be some hoops for us to jump through to ensure that the data we wish to access is secure. Before we can execute commands against the database, we need to connect to the database server, giving us a session. Sessions are designed to be long-lived, so you connect once, perform many requests, and then eventually disconnect. There is a small overhead during connection. That may become noticeable if you connect/disconnect repeatedly, so you may wish to investigate the use of connection pools. Connection pools allow pre-connected sessions to be served quickly to you when you wish to reconnect. Getting ready First, catch your database. If you don't know where it is, we'll probably have difficulty accessing it. There may be more than one, and you'll need to know the right database to access, and have the authority to connect to it. How to do it... You need to specify the following fi ve parameters to connect to PostgreSQL: host or host address port database name user password (or other means of authentication, if any) To connect, there must be a PostgreSQL server running on host, listening on port number port. On that server, a database named dbname and user must also exist. The host must explicitly allow connections from your client—this is explained in the next recipe, and you must also pass authentication using the method the server specifi es. For example, specifying a password won't work if the server has requested a different form of authentication. Almost all PostgreSQL interfaces use the libpq interface library . When using libpq, most of the connection parameter handling is identical, so we can just discuss that once. If you don't specify the preceding parameters, we look for values set through environment variables, which are as follows: PGHOST or PGHOSTADDR PGPORT (or set to 5432 if this is not set) PGDATABASE PGUSER PGPASSWORD (though this one is defi nitely not recommended) If you specify the first four parameters somehow, but not the password, then we look for a password file. Some PostgreSQL interfaces use the client-server protocol directly, so the way defaults are handled may differ. The information we need to supply won't vary signifi cantly, so please check the exact syntax for that interface. How it works... The PostgreSQL server is a client-server database. The system it runs on is known as the host. We can access the PostgreSQL server remotely through the network. However, we must specify the host, which is a hostname, or a hostaddr , which is an IP address. We can specify a host of "localhost" if we wish to make a TCP/IP connection to the same system. It is often better to use a Unix socket connection, which is attempted if the host begins with a slash (/) and the name is presumed to be a directory name (default is /tmp). On any system, there can be more than one database server. Each database server listens on exactly one "well-known" network port , which cannot be shared between servers on the same system. The default port number for PostgreSQL is 5432, which has been registered with IANA, and is uniquely assigned to PostgreSQL. (You can see it used in the /etc/services file on most *nix servers). The port number can be used to uniquely identify a specific database server if many exist. A database server is also sometimes known as a "database cluster", because the PostgreSQL server allows you to define one or more databases on each server. Each connection request must identify exactly one database identifi ed by its dbname. When you connect, you will only be able to see database objects created within that database. A database user is used to identify the connection. By default, there is no limit on the number of connections for a particular user. In more recent versions of PostgreSQL, users are referred to as login roles, though many clues remind us of the earlier naming, and it still makes sense in many ways. A login role is a role that has been assigned the CONNECT privilege. Each connection will typically be authenticated in some way. This is defined at the server, so is not optional at connection time if the administrator has confi gured the server to require authentication. Once you've connected, each connection can have one active transaction at a time and one fully active statement at any time. The server will have a defined limit on the number of connections it can serve, so a connection request can be refused if the server is oversubscribed. Inspecting your connection information If you want to confirm you've connected to the right place and in the right way, you can execute some or all of the following commands: SELECT inet_server_port(); This shows the port on which the server is listening. SELECT current_database(); Shows the current database. SELECT current_user; This shows the current userid. SELECT inet_server_addr(); Shows the IP address of the server that accepted the connection. A user's password is not accessible using general SQL for obvious reasons. You may also need the following: SELECT version(); See also There are many other snippets of information required to understand connections. Some of those are mentioned in this article. For further details, please consult the PostgreSQL server documentation.
Read more
  • 0
  • 0
  • 2182

article-image-joomla-15-top-extensions-adding-booking-system-events
Packt
25 Oct 2010
4 min read
Save for later

Joomla! 1.5 Top Extensions: Adding a Booking System for Events

Packt
25 Oct 2010
4 min read
Joomla! 1.5 Top Extensions Cookbook Over 80 great recipes for taking control of Joomla! Extensions Set up and use the best extensions available for Joomla! Covers extensions for just about every use of Joomla! Packed with recipes to help you get the most of the Joomla! extensions Part of Packt's Cookbook series: Each recipe is a carefully organized sequence of instructions to complete the task as efficiently as possible Getting ready... The Seminar for Joomla! component allows visitors to register for events. Download this component from http://seminar.vollmar.ws/downloads/com_Seminar_V1.3.0.zip, and install it from the Extensions | Install/Uninstall screen in the Joomla! administration panel. How to do it... Once installed, follow these steps to allow registration for events: From the Joomla! administration panel, select Components | Seminar. It shows the Events screen, listing the available events. To create event categories, click on Categories and then click on New. This shows you the Category: [New] screen. On the Category: [New] screen, type in the Title and Alias, and select Yes in the Published radio box. Then select the Access Level, Image, and Image Position. Enter a description for the category. Click on Save in the toolbar. Repeat this step to add as many categories as you need. Click on Events and then click on New. It will show you the New Event screen. Type the Title of the event. Then select Begin, End, Closing Date, and the time of the event. Select Yes in the Display field if you want to show this information. Type a brief description of the event, and the place of the event. Select an organizer from the Organiser drop-down list. Then type the maximum number of participants in the Max. Particip. field. Also, select what to do when the number of participants exceeds this number. When this is done, click on Additional Settings. This shows you the Additional Settings screen. In the Additional Settings section, you can add an additional description. In the Description box, add descriptions to particular groups of visitors. The syntax to add messages for different groups is shown above the text box. Select an image for the event overview. Then type the tutor's name, target group, and the fees per person. Then click on General Input Fields. This will show the following screen: In the General Input Fields section, you can include additional fields. To add additional fields, follow the syntax provided. When this is done, click on Files. This shows the following screen for file upload. Click on the Browse button and select the file to upload. Type a description of the file and select the group that can view it. When this is done, click on the Save button in the toolbar. Select Menus | Main Menu, and then click on New. This will show you the Menu Item: [New] wizard. In the Select Menu Item Type section, select Seminar and provide a title for the menu item on the next screen. Then save the menu item. Preview the site's frontend, as a user logged in to the frontend, and click on the menu item for the seminar. This will display the following screen showing your added event. The overview of the event shows the overview image, event title, category, reservation information, and an indicator for the booking status. Click on the event title, it will show you the event details, as shown in the following screenshot: Select the spaces to be booked. Then type your Name and Email address and click on the Book button. This books your space for the event. You can view your booking by clicking the My Bookings tab, as shown in the following screenshot. Note that your participation status is indicated through a color-coded indicator. There's more... Most of the features of Seminar for the Joomla! component can be configured from the Settings screen. For example, you can configure who can book events, what happens when booking exceeds the number of seats, who can rate the events from the frontend, which folder will store images of the events, the maximum file upload size, the file extensions allowed for uploads, and so on. Summary This article showed you how to allow visitors to register for an event. Further resources on this subject: Adding an Event Calendar to your Joomla! Site using JEvents Showing your Google calendar on your Joomla! site using GCalendar Joomla! 1.5 Top Extensions for Using Languages Manually Translating Your Joomla! Site's Content into Your Desired Language
Read more
  • 0
  • 0
  • 2471
Modal Close icon
Modal Close icon