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-getting-started-draftsight
Packt
10 Sep 2013
10 min read
Save for later

Getting Started with DraftSight

Packt
10 Sep 2013
10 min read
(For more resources related to this topic, see here.) Downloading and starting DraftSight The DWG file format is the most used Computer Aided Design (CAD) format. It is used in all areas of technical drawings. Another drawing file format is DXF, mainly used for communication between CAD programs. There are several programs that work with DWG and DXF files, with similar commands and work processes, with DraftSight being among them. Dassault Systèmes (www.3ds.com), one of the two major CAD companies in the world, licenses the ARES Commander software from Graebert GmbH (www.graebert.com) and uses it as the CAD engine. The first version was released in February 2011. Currently there are versions for Windows 32-bit, Windows 64-bit (XP, Vista, and 7), Mac OS X, and several Linux operating systems (Fedora, Suze, Mandriva, or Ubuntu). Actually, there are 15 languages available, including English, French, German, Spanish, Italian, Portuguese, Chinese (traditional and simplified), and Russian. DraftSight is free for any personal or commercial application. DraftSight can be downloaded from www.draftsight.com, selecting the proper operating system. The executable file is around 100 MB and installs very fast. It does not prompt for the language selection, thus installing the local language, but this can be changed after starting DraftSight. After installation, DraftSight can be initiated by double-clicking the DraftSight desktop icon or by accessing the Windows Start menu and navigating to All Programs | DassaultSystemes | DraftSight. Understanding the user interface When starting DraftSight, its graphical user interface is displayed with a blank new drawing called NONAME_0.DWG. The interface can be customized; it contains the following elements by default, which are displayed in the screenshot in the following section: Drawing area: This area contains the drawing, where graphical entities are inserted, viewed, modified, inquired, or deleted. All colors can be configured. Cursor: The cursor is controlled by the mouse or other pointing device, which will allow specifying points to create, modify, or select entities, also to access menus or toolbars. The cursor coordinates are displayed at the status line. Coordinate system icon: This icon displays the positive directions for the X and Y axis. DraftSight, as with other CAD programs, uses a Cartesian coordinate system, where each point is perfectly identified by a pair of coordinates. Main menu: This top pull-down menu includes most DraftSight commands, divided by categories. Standard toolbar: This toolbar includes the main commands for starting, opening, saving or printing drawings, for cutting, copying, or pasting entities, for painting properties between entities, undoing and redoing, for visualization operations, and controlling the properties palette. Layers toolbar: This toolbar includes the LAYER command and the layers list. Properties toolbar: This toolbar includes the default color, default line type, and default lineweight for new entities or for selected entities. It is advisable to maintain these ByLayer (controlled by layer, thus not explicitly). Draw toolbar: This toolbar includes the main drafting commands, such as creating lines, circles, arcs, and text. Modify toolbar: This toolbar includes the main modifying commands, such as deleting, moving, copying, and rotating. Properties palette: Some DraftSight commands display a palette, which can always be visible. This palette can be turned off, as it will not be required now. Model/Sheets tabs: Drawings are made on the model space. Sheets spaces are specific to prepare sheets for printing. Command window: This is one of the most important interface areas. It includes all requests from the program, displaying available options, and where users can write command names, their aliases, or options. The last line indicates that DraftSight is prompting the colon (:), which means it is waiting for a command. The command window can be resized or moved. Status bar: This bar, beneath the command window, includes the cursor coordinates and the access to drafting auxiliary tools. When hovering over a toolbar icon or a menu item, a small help and the command name are displayed on the left. Configuring DraftSight First, we may choose a different language for using DraftSight. When installing, a language based on user's location is automatically applied, which may not be the desired one. To choose a different language, the _LANGUAGE command must be applied (without forgetting underscore before command name) along with the language corresponding number (a question mark displays all available). Then, reinitiating DraftSight will set up the chosen language. It is very simple to configure DraftSight. The OPTIONS command includes almost all settings and system options. We can access the command by digitizing its name, OP as its alias, choosing Options on the menu displayed by pressing the mouse right button, or Options on the Tools main menu. The command displays a dialog box with several sections on the left column. Choosing one of these sections, the corresponding options are displayed on the right area with a tree structure: File Locations: This section allows defining the location of important files and specific file names, including the Support Files Search Path, default Drawing Files Location, or External References Files Location. System Options: This includes general options related to the system, such as Element Colors to configure interface colors (displayed in the following screenshot), DWG version for saving, Printing options, or Auto-save & Backup options. User Preferences: Here we can define several Drafting and Mouse user options, as well as aliases for commands. Drawing Settings: This includes settings specific to the current drawing. The most important settings are presented in the following screenshot. Drafting Styles: This section includes Active Drafting Styles and the possibility to create or modify text styles, dimension styles, rich line (multiline) styles, and table styles. Profiles: Here it is possible to manage user profiles in order to easily change multiple options at once. The default drawing area is black. A white drawing area was adopted throughout this article to improve images visualization. Starting and setting up a drawing After configuring DraftSight, let's start a new drawing and configure it. Starting a drawing The NEW command (shortcut Ctrl + N, on the Standard toolbar, or File main menu) allows us to start a drawing. The command displays a standard file dialog box in order to choose the template. When starting a new drawing, we may start from a blank drawing (any one coming with DraftSight) or from a template with some configurations already done. Templates are drawing files with the DWT extension by default, placed at C:UsersuserAppDataRoamingDraftSight1.2.265Template or similar, depending on the operating system and DraftSight version. With the OPTIONS command, going to the File Locations | Drawing Support | Drawing Template File Location, we may change this location. To create a template, we prepare the drawing to be used and then apply the SAVEAS command by selecting Drawing Template (*.dwt) on Save as type list. The SMARTNEW command (no alias or icon) allows us to start a new drawing without displaying the file dialog box. We may configure which template will be applied with the OPTIONS command, System Options | Open / Save As | Template file name for SmartNew. Setting up a drawing When using a blank template (for instance, standardiso.dwt, coming with DraftSight), we may configure it, especially units. Again with the OPTIONS command, going to Drawing Settings | Unit System, we can configure the following drawing options: Base angle: We control the base angle direction, from which absolute angles are measured, by clicking on the compass or by writing a value. By default, 0° is East (3 o'clock). Normally, angles are measured positively in the counter clockwise direction, unless Clockwise is checked. Length: The Type list allows the linear unit to be defined and the Precision resolution (number of decimal places or fractions) to be displayed in coordinates or answer to inquiry commands. Angle: The Type list allows the angular unit to be defined and the Precision resolution (number of decimal places or other) to be displayed in coordinates or answer to inquiry commands. Units scale: The Block units format list identifies the drawing unit when inserting contents like blocks or images. With this option, DraftSight automatically applies the suitable scale factor when inserting a block whose unit is different from the drawing unit. A block is a set of objects constituting a single object, like a door or a bolt; its creation or modification. Preview: This simply displays a preview of linear and angular units. By digitizing the UNITSYSTEM command name we get access directly to this section of the OPTIONS command. But a better way is to simply digitize UN (or UNITS). Opening, saving, and closing drawings The OPEN command (shortcut Ctrl + O, on the Standard toolbar or File main menu) opens a drawing in formats DWG or DXF. Also, it allows opening template files, DWT extension, to edit these. It only displays a standard file dialog box to select the file, including a preview area. DraftSight allows several open drawings. To activate another open drawing, we may press Ctrl + Tab or apply the Window main menu and select the drawing by its name. When saving drawings, there are two commands depending on whether or not you want to modify the name or location. The SAVE command (shortcut Ctrl + S, on the Standard toolbar, or File main menu) saves the current drawing, maintaining its format, name and location. If the current drawing has no name, the next command is automatically applied. If we want to modify the name, location, type of file, or version, the SAVEAS command (shortcut Ctrl + Shift + S or the File main menu) must be used. This command displays a standard file dialog box and we can specify name, location and type/version of drawing file. On the Save as type list, as displayed on next image, there are several possibilities covering all DWG and DXF versions for last twenty years. Saving as a template, DWT file is also available. There is a third command to save drawings, called SAVEALL (no alias and not on menus). This one allows us to save all open drawings at once. To close the current drawing without closing DraftSight, the CLOSE command (File main menu)should be applied. This is equivalent of pressing the lower X button on the upper-right corner of the user interface. If the drawing has modifications that have not yet been saved, a warning box is displayed, reminding us to save the drawing. The CLOSEALL command (Window main menu) allows us to close all drawings without closing DraftSight. To each drawing that has modifications not yet saved, a warning box is displayed, allowing us to save that drawing. To quit DraftSight, the EXIT command should be used. This is the equivalent of pressing the upper X button on the upper-right corner of the user interface. If any drawing has modifications that have not yet been saved, a warning box is displayed, allowing us to save that drawing. Summary In this article, we covered an introduction to the free DraftSight program, including where to download, how to start and how to configure it, followed by creating and configuring a drawing, namely units. Then, all commands to open, save, and close were presented. Resources for Article: Further resources on this subject: Introduction to 3D Design using AutoCAD [Article] Dynamically enable a control (Become an expert) [Article] Working with Away3D Cameras [Article]
Read more
  • 0
  • 0
  • 9216

article-image-postgresql-extensible-rdbms
Packt
03 Mar 2015
18 min read
Save for later

PostgreSQL as an Extensible RDBMS

Packt
03 Mar 2015
18 min read
This article by Usama Dar, the author of the book PostgreSQL Server Programming - Second Edition, explains the process of creating a new operator, overloading it, optimizing it, creating index access methods, and much more. PostgreSQL is an extensible database. I hope you've learned this much by now. It is extensible by virtue of the design that it has. As discussed before, PostgreSQL uses a catalog-driven design. In fact, PostgreSQL is more catalog-driven than most of the traditional relational databases. The key benefit here is that the catalogs can be changed or added to, in order to modify or extend the database functionality. PostgreSQL also supports dynamic loading, that is, a user-written code can be provided as a shared library, and PostgreSQL will load it as required. (For more resources related to this topic, see here.) Extensibility is critical for many businesses, which have needs that are specific to that business or industry. Sometimes, the tools provided by the traditional database systems do not fulfill those needs. People in those businesses know best how to solve their particular problems, but they are not experts in database internals. It is often not possible for them to cook up their own database kernel or modify the core or customize it according to their needs. A truly extensible database will then allow you to do the following: Solve domain-specific problems in a seamless way, like a native solution Build complete features without modifying the core database engine Extend the database without interrupting availability PostgreSQL not only allows you to do all of the preceding things, but also does these, and more with utmost ease. In terms of extensibility, you can do the following things in a PostgreSQL database: Create your own data types Create your own functions Create your own aggregates Create your own operators Create your own index access methods (operator classes) Create your own server programming language Create foreign data wrappers (SQL/MED) and foreign tables What can't be extended? Although PostgreSQL is an extensible platform, there are certain things that you can't do or change without explicitly doing a fork, as follows: You can't change or plug in a new storage engine. If you are coming from the MySQL world, this might annoy you a little. However, PostgreSQL's storage engine is tightly coupled with its executor and the rest of the system, which has its own benefits. You can't plug in your own planner/parser. One can argue for and against the ability to do that, but at the moment, the planner, parser, optimizer, and so on are baked into the system and there is no possibility of replacing them. There has been some talk on this topic, and if you are of the curious kind, you can read some of the discussion at http://bit.ly/1yRMkK7. We will now briefly discuss some more of the extensibility capabilities of PostgreSQL. We will not dive deep into the topics, but we will point you to the appropriate link where more information can be found. Creating a new operator Now, let's take look at how we can add a new operator in PostgreSQL. Adding new operators is not too different from adding new functions. In fact, an operator is syntactically just a different way to use an existing function. For example, the + operator calls a built-in function called numeric_add and passes it the two arguments. When you define a new operator, you must define the data types that the operator expects as arguments and define which function is to be called. Let's take a look at how to define a simple operator. You have to use the CREATE OPERATOR command to create an operator. Let's use that function to create a new Fibonacci operator, ##, which will have an integer on its left-hand side: CREATE OPERATOR ## (PROCEDURE=fib, LEFTARG=integer); Now, you can use this operator in your SQL to calculate a Fibonacci number: testdb=# SELECT 12##;?column?----------144(1 row) Note that we defined that the operator will have an integer on the left-hand side. If you try to put a value on the right-hand side of the operator, you will get an error: postgres=# SELECT ##12;ERROR: operator does not exist: ## integer at character 8HINT: No operator matches the given name and argument type(s). Youmight need to add explicit type casts.STATEMENT: select ##12;ERROR: operator does not exist: ## integerLINE 1: select ##12;^HINT: No operator matches the given name and argument type(s). Youmight need to add explicit type casts. Overloading an operator Operators can be overloaded in the same way as functions. This means, that an operator can have the same name as an existing operator but with a different set of argument types. More than one operator can have the same name, but two operators can't share the same name if they accept the same types and positions of the arguments. As long as there is a function that accepts the same kind and number of arguments that an operator defines, it can be overloaded. Let's override the ## operator we defined in the last example, and also add the ability to provide an integer on the right-hand side of the operator: CREATE OPERATOR ## (PROCEDURE=fib, RIGHTARG=integer); Now, running the same SQL, which resulted in an error last time, should succeed, as shown here: testdb=# SELECT ##12;?column?----------144(1 row) You can drop the operator using the DROP OPERATOR command. You can read more about creating and overloading new operators in the PostgreSQL documentation at http://www.postgresql.org/docs/current/static/sql-createoperator.html and http://www.postgresql.org/docs/current/static/xoper.html. There are several optional clauses in the operator definition that can optimize the execution time of the operators by providing information about operator behavior. For example, you can specify the commutator and the negator of an operator that help the planner use the operators in index scans. You can read more about these optional clauses at http://www.postgresql.org/docs/current/static/xoper-optimization.html. Since this article is just an introduction to the additional extensibility capabilities of PostgreSQL, we will just introduce a couple of optimization options; any serious production quality operator definitions should include these optimization clauses, if applicable. Optimizing operators The optional clauses tell the PostgreSQL server about how the operators behave. These options can result in considerable speedups in the execution of queries that use the operator. However, if you provide these options incorrectly, it can result in a slowdown of the queries. Let's take a look at two optimization clauses called commutator and negator. COMMUTATOR This clause defines the commuter of the operator. An operator A is a commutator of operator B if it fulfils the following condition: x A y = y B x. It is important to provide this information for the operators that will be used in indexes and joins. As an example, the commutator for > is <, and the commutator of = is = itself. This helps the optimizer to flip the operator in order to use an index. For example, consider the following query: SELECT * FROM employee WHERE new_salary > salary; If the index is defined on the salary column, then PostgreSQL can rewrite the preceding query as shown: SELECT * from employee WHERE salary < new_salary This allows PostgreSQL to use a range scan on the index column salary. For a user-defined operator, the optimizer can only do this flip around if the commutator of a user-defined operator is defined: CREATE OPERATOR > (LEFTARG=integer, RIGHTARG=integer, PROCEDURE=comp, COMMUTATOR = <) NEGATOR The negator clause defines the negator of the operator. For example, <> is a negator of =. Consider the following query: SELECT * FROM employee WHERE NOT (dept = 10); Since <> is defined as a negator of =, the optimizer can simplify the preceding query as follows: SELECT * FROM employee WHERE dept <> 10; You can even verify that using the EXPLAIN command: postgres=# EXPLAIN SELECT * FROM employee WHERE NOTdept = 'WATER MGMNT';QUERY PLAN---------------------------------------------------------Foreign Scan on employee (cost=0.00..1.10 rows=1 width=160)Filter: ((dept)::text <> 'WATER MGMNT'::text)Foreign File: /Users/usamadar/testdata.csvForeign File Size: 197(4 rows) Creating index access methods Let's discuss how to index new data types or user-defined types and operators. In PostgreSQL, an index is more of a framework that can be extended or customized for using different strategies. In order to create new index access methods, we have to create an operator class. Let's take a look at a simple example. Let's consider a scenario where you have to store some special data such as an ID or a social security number in the database. The number may contain non-numeric characters, so it is defined as a text type: CREATE TABLE test_ssn (ssn text);INSERT INTO test_ssn VALUES ('222-11-020878');INSERT INTO test_ssn VALUES ('111-11-020978'); Let's assume that the correct order for this data is such that it should be sorted on the last six digits and not the ASCII value of the string. The fact that these numbers need a unique sort order presents a challenge when it comes to indexing the data. This is where PostgreSQL operator classes are useful. An operator allows a user to create a custom indexing strategy. Creating an indexing strategy is about creating your own operators and using them alongside a normal B-tree. Let's start by writing a function that changes the order of digits in the value and also gets rid of the non-numeric characters in the string to be able to compare them better: CREATE OR REPLACE FUNCTION fix_ssn(text)RETURNS text AS $$BEGINRETURN substring($1,8) || replace(substring($1,1,7),'-','');END;$$LANGUAGE 'plpgsql' IMMUTABLE; Let's run the function and verify that it works: testdb=# SELECT fix_ssn(ssn) FROM test_ssn;fix_ssn-------------0208782221102097811111(2 rows) Before an index can be used with a new strategy, we may have to define some more functions depending on the type of index. In our case, we are planning to use a simple B-tree, so we need a comparison function: CREATE OR REPLACE FUNCTION ssn_compareTo(text, text)RETURNS int AS$$BEGINIF fix_ssn($1) < fix_ssn($2)THENRETURN -1;ELSIF fix_ssn($1) > fix_ssn($2)THENRETURN +1;ELSERETURN 0;END IF;END;$$ LANGUAGE 'plpgsql' IMMUTABLE; It's now time to create our operator class: CREATE OPERATOR CLASS ssn_opsFOR TYPE text USING btreeASOPERATOR 1 < ,OPERATOR 2 <= ,OPERATOR 3 = ,OPERATOR 4 >= ,OPERATOR 5 > ,FUNCTION 1 ssn_compareTo(text, text); You can also overload the comparison operators if you need to compare the values in a special way, and use the functions in the compareTo function as well as provide them in the CREATE OPERATOR CLASS command. We will now create our first index using our brand new operator class: CREATE INDEX idx_ssn ON test_ssn (ssn ssn_ops); We can check whether the optimizer is willing to use our special index, as follows: testdb=# SET enable_seqscan=off;testdb=# EXPLAIN SELECT * FROM test_ssn WHERE ssn = '02087822211';QUERY PLAN------------------------------------------------------------------Index Only Scan using idx_ssn on test_ssn (cost=0.13..8.14 rows=1width=32)Index Cond: (ssn = '02087822211'::text)(2 rows) Therefore, we can confirm that the optimizer is able to use our new index. You can read about index access methods in the PostgreSQL documentation at http://www.postgresql.org/docs/current/static/xindex.html. Creating user-defined aggregates User-defined aggregate functions are probably a unique PostgreSQL feature, yet they are quite obscure and perhaps not many people know how to create them. However, once you are able to create this function, you will wonder how you have lived for so long without using this feature. This functionality can be incredibly useful, because it allows you to perform custom aggregates inside the database, instead of querying all the data from the client and doing a custom aggregate in your application code, that is, the number of hits on your website per minute from a specific country. PostgreSQL has a very simple process for defining aggregates. Aggregates can be defined using any functions and in any languages that are installed in the database. Here are the basic steps to building an aggregate function in PostgreSQL: Define a start function that will take in the values of a result set; this function can be defined in any PL language you want. Define an end function that will do something with the final output of the start function. This can be in any PL language you want. Define the aggregate using the CREATE AGGREGATE command, providing the start and end functions you just created. Let's steal an example from the PostgreSQL wiki at http://wiki.postgresql.org/wiki/Aggregate_Median. In this example, we will calculate the statistical median of a set of data. For this purpose, we will define start and end aggregate functions. Let's define the end function first, which takes an array as a parameter and calculates the median. We are assuming here that our start function will pass an array to the following end function: CREATE FUNCTION _final_median(anyarray) RETURNS float8 AS $$WITH q AS(SELECT valFROM unnest($1) valWHERE VAL IS NOT NULLORDER BY 1),cnt AS(SELECT COUNT(*) AS c FROM q)SELECT AVG(val)::float8FROM(SELECT val FROM qLIMIT 2 - MOD((SELECT c FROM cnt), 2)OFFSET GREATEST(CEIL((SELECT c FROM cnt) / 2.0) - 1,0)) q2;$$ LANGUAGE sql IMMUTABLE; Now, we create the aggregate as shown in the following code: CREATE AGGREGATE median(anyelement) (SFUNC=array_append,STYPE=anyarray,FINALFUNC=_final_median,INITCOND='{}'); The array_append start function is already defined in PostgreSQL. This function appends an element to the end of an array. In our example, the start function takes all the column values and creates an intermediate array. This array is passed on to the end function, which calculates the median. Now, let's create a table and some test data to run our function: testdb=# CREATE TABLE median_test(t integer);CREATE TABLEtestdb=# INSERT INTO median_test SELECT generate_series(1,10);INSERT 0 10 The generate_series function is a set returning function that generates a series of values, from start to stop with a step size of one. Now, we are all set to test the function: testdb=# SELECT median(t) FROM median_test;median--------5.5(1 row) The mechanics of the preceding example are quite easy to understand. When you run the aggregate, the start function is used to append all the table data from column t into an array using the append_array PostgreSQL built-in. This array is passed on to the final function, _final_median, which calculates the median of the array and returns the result in the same data type as the input parameter. This process is done transparently to the user of the function who simply has a convenient aggregate function available to them. You can read more about the user-defined aggregates in the PostgreSQL documentation in much more detail at http://www.postgresql.org/docs/current/static/xaggr.html. Using foreign data wrappers PostgreSQL foreign data wrappers (FDW) are an implementation of SQL Management of External Data (SQL/MED), which is a standard added to SQL in 2013. FDWs are drivers that allow PostgreSQL database users to read and write data to other external data sources, such as other relational databases, NoSQL data sources, files, JSON, LDAP, and even Twitter. You can query the foreign data sources using SQL and create joins across different systems or even across different data sources. There are several different types of data wrappers developed by different developers and not all of them are production quality. You can see a select list of wrappers on the PostgreSQL wiki at http://wiki.postgresql.org/wiki/Foreign_data_wrappers. Another list of FDWs can be found on PGXN at http://pgxn.org/tag/fdw/. Let's take look at a small example of using file_fdw to access data in a CSV file. First, you need to install the file_fdw extension. If you compiled PostgreSQL from the source, you will need to install the file_fdw contrib module that is distributed with the source. You can do this by going into the contrib/file_fdw folder and running make and make install. If you used an installer or a package for your platform, this module might have been installed automatically. Once the file_fdw module is installed, you will need to create the extension in the database: postgres=# CREATE EXTENSION file_fdw;CREATE EXTENSION Let's now create a sample CSV file that uses the pipe, |, as a separator and contains some employee data: $ cat testdata.csvAARON, ELVIA J|WATER RATE TAKER|WATER MGMNT|81000.00|73862.00AARON, JEFFERY M|POLICE OFFICER|POLICE|74628.00|74628.00AARON, KIMBERLEI R|CHIEF CONTRACT EXPEDITER|FLEETMANAGEMNT|77280.00|70174.00 Now, we should create a foreign server that is pretty much a formality because the file is on the same server. A foreign server normally contains the connection information that a foreign data wrapper uses to access an external data resource. The server needs to be unique within the database: CREATE SERVER file_server FOREIGN DATA WRAPPER file_fdw; The next step, is to create a foreign table that encapsulates our CSV file: CREATE FOREIGN TABLE employee (emp_name VARCHAR,job_title VARCHAR,dept VARCHAR,salary NUMERIC,sal_after_tax NUMERIC) SERVER file_serverOPTIONS (format 'csv',header 'false' , filename '/home/pgbook/14/testdata.csv', delimiter '|', null '');''); The CREATE FOREIGN TABLE command creates a foreign table and the specifications of the file are provided in the OPTIONS section of the preceding code. You can provide the format, and if the first line of the file is a header (header 'false'), in our case there is no file header. We then provide the name and path of the file and the delimiter used in the file, which in our case is the pipe symbol |. In this example, we also specify that the null values should be represented as an empty string. Let's run a SQL command on our foreign table: postgres=# select * from employee;-[ RECORD 1 ]-+-------------------------emp_name | AARON, ELVIA Jjob_title | WATER RATE TAKERdept | WATER MGMNTsalary | 81000.00sal_after_tax | 73862.00-[ RECORD 2 ]-+-------------------------emp_name | AARON, JEFFERY Mjob_title | POLICE OFFICERdept | POLICEsalary | 74628.00sal_after_tax | 74628.00-[ RECORD 3 ]-+-------------------------emp_name | AARON, KIMBERLEI Rjob_title | CHIEF CONTRACT EXPEDITERdept | FLEET MANAGEMNTsalary | 77280.00sal_after_tax | 70174.00 Great, looks like our data is successfully loaded from the file. You can also use the d meta command to see the structure of the employee table: postgres=# d employee;Foreign table "public.employee"Column | Type | Modifiers | FDW Options---------------+-------------------+-----------+-------------emp_name | character varying | |job_title | character varying | |dept | character varying | |salary | numeric | |sal_after_tax | numeric | |Server: file_serverFDW Options: (format 'csv', header 'false',filename '/home/pg_book/14/testdata.csv', delimiter '|',"null" '') You can run explain on the query to understand what is going on when you run a query on the foreign table: postgres=# EXPLAIN SELECT * FROM employee WHERE salary > 5000;QUERY PLAN---------------------------------------------------------Foreign Scan on employee (cost=0.00..1.10 rows=1 width=160)Filter: (salary > 5000::numeric)Foreign File: /home/pgbook/14/testdata.csvForeign File Size: 197(4 rows) The ALTER FOREIGN TABLE command can be used to modify the options. More information about the file_fdw is available at http://www.postgresql.org/docs/current/static/file-fdw.html. You can take a look at the CREATE SERVER and CREATE FOREIGN TABLE commands in the PostgreSQL documentation for more information on the many options available. Each of the foreign data wrappers comes with its own documentation about how to use the wrapper. Make sure that an extension is stable enough before it is used in production. The PostgreSQL core development group does not support most of the FDW extensions. If you want to create your own data wrappers, you can find the documentation at http://www.postgresql.org/docs/current/static/fdwhandler.html as an excellent starting point. The best way to learn, however, is to read the code of other available extensions. Summary This includes the ability to add new operators, new index access methods, and create your own aggregates. You can access foreign data sources, such as other databases, files, and web services using PostgreSQL foreign data wrappers. These wrappers are provided as extensions and should be used with caution, as most of them are not officially supported. Even though PostgreSQL is very extensible, you can't plug in a new storage engine or change the parser/planner and executor interfaces. These components are very tightly coupled with each other and are, therefore, highly optimized and mature. Resources for Article: Further resources on this subject: Load balancing MSSQL [Article] Advanced SOQL Statements [Article] Running a PostgreSQL Database Server [Article]
Read more
  • 0
  • 0
  • 9211

article-image-storage-scalability
Packt
11 Aug 2015
17 min read
Save for later

Storage Scalability

Packt
11 Aug 2015
17 min read
In this article by Victor Wu and Eagle Huang, authors of the book, Mastering VMware vSphere Storage, we will learn that, SAN storage is a key component of a VMware vSphere environment. We can choose different vendors and types of SAN storage to deploy on a VMware Sphere environment. The advanced settings of each storage can affect the performance of the virtual machine, for example, FC or iSCSI SAN storage. It has a different configuration in a VMware vSphere environment. Host connectivity of Fibre Channel storage is accessed by Host Bus Adapter (HBA). Host connectivity of iSCSI storage is accessed by the TCP/IP networking protocol. We first need to know the concept of storage. Then we can optimize the performance of storage in a VMware vSphere environment. In this article, you will learn these topics: What the vSphere storage APIs for Array Integration (VAAI) and Storage Awareness (VASA) are The virtual machine storage profile VMware vSphere Storage DRS and VMware vSphere Storage I/O Control (For more resources related to this topic, see here.) vSphere storage APIs for array integration and storage awareness VMware vMotion is a key feature in vSphere hosts. An ESXi host cannot provide the vMotion feature if it is without shared SAN storage. SAN storage is a key component in a VMware vSphere environment. In large-scale virtualization environments, there are many virtual machines stored in SAN storage. When a VMware administrator executes virtual machine cloning or migrates a virtual machine to another ESXi host by vMotion, this operation allocates the resource on that ESXi host and SAN storage. In vSphere 4.1 and later versions, it can support VAAI. The vSphere storage API is used by a storage vendor who provides hardware acceleration or offloads vSphere I/O between storage devices. These APIs can reduce the resource overhead on ESXi hosts and improve performance for ESXi host operations, for example, vMotion, virtual machine cloning, creating a virtual machine, and so on. VAAI has two APIs: the hardware acceleration API and the array thin provisioning API. The hardware acceleration API is used to integrate with VMware vSphere to offload storage operations to the array and reduce the CPU overload on the ESXi host. The following table lists the features of the hardware acceleration API for block and NAS: Array integration Features Description Block Fully copy This blocks clone or copy offloading. Block zeroing This is also called write same. When you provision an eagerzeroedthick VMDK, the SCSI command is issued to write zeroes to disks. Atomic Test & Set (ATS) This is a lock mechanism that prevents the other ESXi host from updating the same VMFS metadata. NAS Full file clone This is similar to Extended Copy (XCOPY) hardware acceleration. Extended statistics This feature is enabled in space usage in the NAS data store. Reserved space The allocated space of virtual disk in thick format. The array thin provisioning API is used to monitor the ESXi data store space on the storage arrays. It helps prevent the disk from running out of space and reclaims disk space. For example, if the storage is assigned as 1 x 3 TB LUN in the ESXi host, but the storage can only provide 2 TB of data storage space, it is considered to be 3 TB in the ESXi host. Streamline its monitoring LUN configuration space in order to avoid running out of physical space. When vSphere administrators delete or remove files from the data store that is provisioned LUN, the storage can reclaim free space in the block level. In vSphere 4.1 or later, it can support VAAI features. In vSphere 5.5, you can reclaim the space on thin provisioned LUN using esxcli. VMware VASA is a piece of software that allows the storage vendor to provide information about their storage array to VMware vCenter Server. The information includes storage capability, the state of physical storage devices, and so on. vCenter Server collects this information from the storage array using a software component called VASA provider, which is provided by the storage array vendor. A VMware administrator can view the information in VMware vSphere Client / VMware vSphere Web Client. The following diagram shows the architecture of VASA with vCenter Server. For example, the VMware administrator requests to create a 1 x data store in VMware ESXi Server. It has three main components: the storage array, the storage provider and VMware vCenter Server. The following is the procedure to add the storage provider to vCenter Server: Log in to vCenter by vSphere Client. Go to Home | Storage Providers. Click on the Add button. Input information about the storage vendor name, URL, and credentials. Virtual machine storage profile The storage provider can help the vSphere administrator know the state of the physical storage devices and the capabilities on which their virtual machines are located. It also helps choose the correct storage in terms of performance and space by using virtual machine storage policies. A virtual machine storage policy helps you ensure that a virtual machine guarantees a specified level of performance or capacity of storage, for example, the SSD/SAS/NL-SAS data store, spindle I/O, and redundancy. Before you define a storage policy, you need to specify the storage requirement for your application that runs on the virtual machine. It has two types of storage requirement, which is storage-vendor-specific storage capability and user-defined storage capability. Storage-vendor-specific storage capability comes from the storage array. The storage vendor provider informs vCenter Server that it can guarantee the use of storage features by using storage-vendor-specific storage capability. vCenter Server assigns vendor-specific storage capability to each ESXi data store. User-defined storage capability is the one that you can define and assign storage profile to each ESXi datastore. In vSphere 5.1/5.5, the name of the storage policy is VM storage profile. Virtual machine storage policies can include one or more storage capabilities and assign to one or more VM. The virtual machine can be checked for storage compliance if it is placed on compliant storage. When you migrate, create, or clone a virtual machine, you can select the storage policy and apply it to that machine. The following procedure shows how to create a storage policy and apply it to a virtual machine in vSphere 5.1 using user-defined storage capability: The vSphere ESXi host requires the license edition of Enterprise Plus to enable the VM storage profile feature. The following procedure is adding the storage profile into vCenter Server: Log in to vCenter Server using vSphere Client. Click on the Home button in the top bar, and choose the VM Storage Profiles button under Management. Click on the Manage Storage Capabilities button to create user-defined storage capability. Click on the Add button to create the name of the storage capacity, for example, SSD Storage, SAS Storage, or NL-SAS Storage. Then click on the Close button. Click on the Create VM Storage Profile button to create the storage policy. Input the name of the VM storage profile, as shown in the following screenshot, and then click on the Next button to select the user-defined storage capability, which is defined in step 4. Click on the Finish button. Assign the user-defined storage capability to your specified ESXi data store. Right-click on the data store that you plan to assign the user-defined storage capability to. This capability is defined in step 4. After creating the VM storage profile, click on the Enable VM Storage Profiles button. Then click on the Enable button to enable the profiles. The following screenshot shows Enable VM Storage Profiles: After enabling the VM storage profile, you can see VM Storage Profile Status as Enabled and Licensing Status as Licensed, as shown in this screenshot: We have successfully created the VM storage profile. Now we have to associate the VM storage profile with a virtual machine. Right-click on a virtual machine that you plan to apply to the VM storage profile, choose VM Storage Profile, and then choose Manage Profiles. From the drop-down menu of VM Storage Profile select your profile. Then you can click on the Propagate to disks button to associate all virtual disks or decide which virtual disks you want to associate with that profile by setting manually. Click on OK. Finally, you need to check the compliance of VM Storage Profile on this virtual machine. Click on the Home button in the top bar. Then choose the VM Storage Profiles button under Management. Go to Virtual Machines and click on the Check Compliance Now button. The Compliance Status will display Compliant after compliance checking, as follows: Pluggable Storage Architecture (PSA) exists in the SCSI middle layer of the VMkernel storage stack. PSA is used to allow thirty-party storage vendors to use their failover and load balancing techniques for their specific storage array. A VMware ESXi host uses its multipathing plugin to control the ownership of the device path and LUN. The VMware default Multipathing Plugin (MPP) is called VMware Native Multipathing Plugin (NMP), which includes two subplugins as components: Storage Array Type Plugin (SATP) and Path Selection Plugin (PSP). SATP is used to handle path failover for a storage array, and PSP is used to issue an I/O request to a storage array. The following diagram shows the architecture of PSA: This table lists the operation tasks of PSA and NMP in the ESXi host:   PSA NMP Operation tasks Discovers the physical paths Manages the physical path Handles I/O requests to the physical HBA adapter and logical devices Creates, registers, and deregisters logical devices Uses predefined claim rules to control storage devices Selects an optimal physical path for the request The following is an example of operation of PSA in a VMkernel storage stack: The virtual machine sends out an I/O request to a logical device that is managed by the VMware NMP. The NMP requests the PSP to assign to this logical device. The PSP selects a suitable physical path to send the I/O request. When the I/O operation is completed successfully, the NMP reports that the I/O operation is complete. If the I/O operation reports an error, the NMP calls the SATP. The SATP fails over to the new active path. The PSP selects a new active path from all available paths and continues the I/O operation. The following diagram shows the operation of PSA: VMware vSphere provides three options for the path selection policy. These are Most Recently Used (MRU), Fixed, and Round Robin (RR). The following table lists the advantages and disadvantages of each path: Path selection Description Advantage Disadvantage MRU The ESXi host selects the first preferred path at system boot time. If this path becomes unavailable, the ESXi host changes to the other active path. You can select your preferred path manually in the ESXi host. The ESXi host does not revert to the original path when that l path becomes available again. Fixed You can select the preferred path manually. The ESXi host can revert to the original path when the preferred path becomes available again. If the ESXi host cannot select the preferred path, it selects an available preferred path randomly. RR The ESXi host uses automatic path selection. The storage I/O across all available paths and enable load balancing across all paths. The storage is required to support ALUA mode. You cannot know which path is preferred because the storage I/O across all available paths. The following is the procedure of changing the path selection policy in an ESXi host: Log in to vCenter Server using vSphere Client. Go to the configuration of your selected ESXi host, choose the data store that you want to configure, and click on the Properties… button. Click on the Manage Paths… button. Select the drop-down menu and click on the Change button. If you plan to deploy a third-party MPP on your ESXi host, you need to follow up the storage vendor's instructions for the installation, for example, EMC PowerPath/VE for VMware that it is a piece of path management software for VMware's vSphere server and Microsoft's Hyper-V server. It also can provide load balancing and path failover features. VMware vSphere Storage DRS VMware vSphere Storage DRS (SDRS) is the placement of virtual machines in an ESX's data store cluster. According to storage capacity and I/O latency, it is used by VMware storage vMotion to migrate the virtual machine to keep the ESX's data store in a balanced status that is used to aggregate storage resources, and enable the placement of the virtual disk (VMDK) of virtual machine and load balancing of existing workloads. What is a data store cluster? It is a collection of ESXi's data stores grouped together. The data store cluster is enabled for vSphere SDRS. SDRS can work in two modes: manual mode and fully automated mode. If you enable SDRS in your environment, when the vSphere administrator creates or migrates a virtual machine, SDRS places all the files (VMDK) of this virtual machine in the same data store or different a data store in the cluster, according to the SDRS affinity rules or anti-affinity rules. The VMware ESXi host cluster has two key features: VMware vSphere High Availability (HA) and VMware vSphere Distributed Resource Scheduler (DRS). SDRS is different from the host cluster DRS. The latter is used to balance the virtual machine across the ESXi host based on the memory and CPU usage. SDRS is used to balance the virtual machine across the SAN storage (ESX's data store) based on the storage capacity and IOPS. The following table lists the difference between SDRS affinity rules and anti-affinity rules: Name of SDRS rules Description VMDK affinity rules This is the default SDRS rule for all virtual machines. It keeps each virtual machine's VMDKs together on the same ESXi data store. VMDK anti-affinity rules Keep each virtual machine's VMDKs on different ESXi data stores. You can apply this rule into all virtual machine's VMDKs or to dedicated virtual machine's VMDKs. VM anti-affinity rules Keep the virtual machine on different ESXi data stores. This rule is similar to the ESX DRS anti-affinity rules. The following is the procedure to create a storage DRS in vSphere 5: Log in to vCenter Server using vSphere Client. Go to home and click on the Datastores and Datastore Clusters button. Right-click on the data center and choose New Datastore Cluster. Input the name of the SDRS and then click on the Next button. Choose Storage DRS mode, Manual Mode and Fully Automated Mode. Manual Mode: According to the placement and migration recommendation, the placement and migration of the virtual machine are executed manually by the user.Fully Automated Mode: Based on the runtime rules, the placement of the virtual machine is executed automatically. Set up SDRS Runtime Rules. Then click on the Next button. Enable I/O metric for SDRS recommendations is used to enable I/O load balancing. Utilized Space is the percentage of consumed space allowed before the storage DRS executes an action. I/O Latency is the percentage of consumed latency allowed before the storage DRS executes an action. This setting can execute only if the Enable I/O metric for SDRS recommendations checkbox is selected. No recommendations until utilization difference between source and destination is is used to configure the space utilization difference threshold. I/O imbalance threshold is used to define the aggressive of IOPs load balancing. This setting can execute only if the Enable I/O metric for SDRS recommendations checkbox is selected. Select the ESXi host that is required to create SDRS. Then click on the Next button. Select the data store that is required to join the data store cluster, and click on the Next button to complete. After creating SDRS, go to the vSphere Storage DRS panel on the Summary tab of the data store cluster. You can see that Storage DRS is Enabled. On the Storage DRS tab on the data store cluster, it displays the recommendation, placement, and reasons. Click on the Apply Recommendations button if you want to apply the recommendations. Click on the Run Storage DRS button if you want to refresh the recommendations. VMware vSphere Storage I/O Control What is VMware vSphere Storage I/O Control? It is used to control in order to share and limit the storage of I/O resources, for example, the IOPS. You can control the number of storage IOPs allocated to the virtual machine. If a certain virtual machine is required to get more storage I/O resources, vSphere Storage I/O Control can ensure that that virtual machine can get more storage I/O than other virtual machines. The following table shows example of the difference between vSphere Storage I/O Control enabled and without vSphere Storage I/O Control: In this diagram, the VMware ESXi Host Cluster does not have vSphere Storage I/O Control. VM 2 and VM 5 need to get more IOPs, but they can allocate only a small amount of I/O resources. On the contrary, VM 1 and VM 3 can allocate a large amount of I/O resources. Actually, both VMs are required to allocate a small amount of IOPs. In this case, it wastes and overprovisions the storage resources. In the diagram to the left, vSphere Storage I/O Control is enabled in the ESXi Host Cluster. VM 2 and VM 5 are required to get more IOPs. They can allocate a large amount of I/O resources after storage I/O control is enabled. VM 1, VM 3, and VM 4 are required to get a small amount of I/O resources, and now these three VMs allocate a small amount of IOPs. After enabling storage I/O control, it helps reduce waste and overprovisioning of the storage resources. When you enable VMware vSphere Storage DRS, vSphere Storage I/O Control is automatically enabled on the data stores in the data store cluster. The following is the procedure to be carried out to enable vSphere Storage I/O control on an ESXi data store, and set up storage I/O shares and limits using vSphere Client 5: Log in to vCenter Server using vSphere Client. Go to the Configuration tab of the ESXi host, select the data store, and then click on the Properties… button. Select Enabled under Storage I/O Control, and click on the Close button. After Storage I/O Control is enabled, you can set up the storage I/O shares and limits on the virtual machine. Right-click on the virtual machine and select Edit Settings. Click on the Resources tab in the virtual machine properties box, and select Disk. You can individually set each virtual disk's Shares and Limit field. By default, all virtual machine shares are set to Normal and with Unlimited IOPs. Summary In this article, you learned what VAAI and VASA are. In a vSphere environment, the vSphere administrator learned how to configure the storage profile in vCenter Server and assign to the ESXi data store. We covered the benefits of vSphere Storage I/O Control and vSphere Storage DRS. When you found that it has a storage performance problem in the vSphere host, we saw how to troubleshoot the performance problem, and found out the root cause. Resources for Article: Further resources on this subject: Essentials of VMware vSphere [Article] Introduction to vSphere Distributed switches [Article] Network Virtualization and vSphere [Article]
Read more
  • 0
  • 0
  • 9208

article-image-cocos2d-iphone-surfing-through-scenes
Packt
29 Dec 2010
10 min read
Save for later

Cocos2d for iPhone: Surfing Through Scenes

Packt
29 Dec 2010
10 min read
  Cocos2d for iPhone 0.99 Beginner's Guide Make mind-blowing 2D games for iPhone with this fast, flexible, and easy-to-use framework! A cool guide to learning cocos2d with iPhone to get you into the iPhone game industry quickly Learn all the aspects of cocos2d while building three different games Add a lot of trendy features such as particles and tilemaps to your games to captivate your players Full of illustrations, diagrams, and tips for building iPhone games, with clear step-by-step instructions and practical examples         Read more about this book       (For more resources on Cocos2d, see here.) We'll be doing a lot of things in this article, so let's get started. Aerial Gun, a vertical shooter game Let's talk about the game we will be making. Aerial Gun, as I said earlier, is a vertical shooter game. That means you will be in control of an airship which will move vertically. Actually, the airship won't be moving anywhere (well except to the left and right); what is really going to move here is the background, giving the sense the airship is the one moving. The player will be able to control the airship by using accelerometer controls. We'll also provide some areas where the player can touch to fire bullets or bombs to destroy the enemies. Enemies will be appearing at different time intervals and will have some different behaviors attached to them. For example, some of them could just move towards the airship, others may stay there and shoot back, and so on. We'll do it in a way you can create more custom behaviors later. For this game we will be using the Cocos2d template again, just because it is the easier way to have a project properly set up, at least to begin our work. So, follow the same steps as when we created the Coloured Stones game. Just open Xcode and go to the File menu, select to create a new project. Then choose the Cocos2d template (the simple one, without any physics engine) and give a name to the project. I will call it AerialGun. Once you do that, your new project should be opened. Creating new scenes We will begin this new game by first doing a couple of scenes other than the one that holds the actual game. If you take a look at the class that the template generates, at first sight you won't find what would appear to be a scene. That is because the template handles that in a confusing fashion, at least for people who are just getting started with Cocos2d. Let's take a look at that. Open the newly generated HelloWorldScene.m file. This is the same code in which we based our first game. This time we will analyze it so you understand what it is doing behind scenes. Take a look at the first method of the implementation of the HelloWorld Layer: +(id) scene{ // 'scene' is an autorelease object. CCScene *scene = [CCScene node]; // 'layer' is an autorelease object. HelloWorld *layer = [HelloWorld node]; // add layer as a child to scene [scene addChild: layer]; // return the scene return scene;} If you remember well, this is the method that get's called in the AppDelegate when the Director needs to start running with a scene. So why are we passing the method of a layer instead of an instance of a CCScene class? If you pay attention to the +(id)scene method of the layer, what it does is to instantiate a CCScene object, then it instantiates a HelloWorld object (the layer), and then it adds that layer to the scene and returns it. This actually works as you have witnessed and is pretty quick to set up, and get you up and running. However, sometimes you will need to have you own custom scenes, that is a class that inherits from CCScene and extends it in some fashion. Now we are going to create some of the scenes that we need for this game and add a layer to each one. Then when it is time to work with the game scene we will modify it to match our needs. Before doing anything, please change the name of the HelloWorldlayer to GameLayer and the name of the HelloWorldScene to GameScene, just as we did back then with our first game. Time for action – creating the splash and main menu scene We will begin with a simple scene, the splash screen. A splash screen is the first thing that appears as you launch a game. Well, the second if you count the Default.png image. The objective of this screen is to show the player some information about the developer, other companies that helped, and so on. Most times you will just show a couple and logos and move to the main menu. So, what we will do now is put a new Default.png image, then create the SplashScene. The Default.png image is located in your project's Resources group folder and it is the first image that is shown when the application is launched. You should always have one, so that something is shown while the application is being launched. This happens before anything is initialized, so you can't do anything else other than show this image. Its dimensions must be 320 * 480 (when developing for older generation iPhones), so if your game is supposed to be in landscape mode, you should rotate the image with any graphics software before including it in your project. The SplashScene is going to show a sprite for a moment, then fade it, show another one and then move to the GameScene. Let's add a new file to the project. Select New File (CMD + N) from the File menu, then select Objective-C class (we are going to do it from scratch anyways) and name it SplashScene. This file will hold both the SplashScene and the SplashLayer classes. The SplashLayer will be added as a child of the SplashScene, and inside the layer we will add the sprites. Before writing any code, add to the project the three splash images I created for you. You can find them in the companion files folder. Once you have them added into your project we can begin working on the SplashScene. The following is the SplashScene.h: #import <Foundation/Foundation.h>#import "cocos2d.h"#import "MainMenuScene.h"@interface SplashScene : CCScene { }@end@interface SplashLayer : CCLayer { }@end And the SplashScene.m file: #import "SplashScene.h" //Here is the implementation of the SplashScene@implementation SplashScene- (id) init{ self = [super init]; if (self != nil) { [self addChild:[SplashLayer node]]; } return self;}-(void)dealloc{ [super dealloc];}@end//And here is the implementation of the SplashLayer@implementation SplashLayer- (id) init{ if ((self = [super init])) { isTouchEnabled = YES; NSMutableArray * splashImages = [[NSMutableArray alloc]init]; for(int i =1;i<=3;i++) { CCSprite * splashImage = [CCSprite spriteWithFile:[NSString stringWithFormat:@"splash%d.png",i]]; [splashImage setPosition:ccp(240,160)]; [self addChild:splashImage]; if(i!=1) [splashImage setOpacity:0]; [splashImages addObject:splashImage]; } [self fadeAndShow:splashImages]; } return self;}//Now we add the methods that handle the image switching-(void)fadeAndShow:(NSMutableArray *)images{ if([images count]<=1) { [images release]; [[CCDirector sharedDirector]replaceScene:[MainMenuScene node]]; } else { CCSprite * actual = (CCSprite *)[images objectAtIndex:0]; [images removeObjectAtIndex:0]; CCSprite * next = (CCSprite *)[images objectAtIndex:0]; [actual runAction:[CCSequence actions:[CCDelayTime actionWithDuration:2], [CCFadeOut actionWithDuration:1],[CCCallFuncN actionWithTarget:self selector:@selector(remove:)],nil]]; [next runAction:[CCSequence actions:[CCDelayTime actionWithDuration:2], [CCFadeIn actionWithDuration:1],[CCDelayTime actionWithDuration:2], [CCCallFuncND actionWithTarget:self selector:@selector(cFadeAndShow: data:) data:images],nil]]; } }-(void) cFadeAndShow:(id)sender data:(void*)data{ NSMutableArray * images = (NSMutableArray *)data; [self fadeAndShow:images];}-(void)remove:(CCSprite *)s{ [s.parent removeChild:s cleanup:YES];}-(void)dealloc{ [super dealloc];}@end As you may notice, I have put together two classes in only one file. You can do this with any number of classes, as long you don't get lost in such a long file. Generally, you will create a pair of files (the .m and .h) for each class, but as the SplashScene class has very little code, I'd rather put it there. For this to work properly, we need to make some other changes. First, open the AerialGunAppDelegate.m file and change the line where the the Director starts running the GameScene. We want it to start by running the SplashScene now. So replace that line with the following: [[CCDirector sharedDirector] runWithScene:[SplashScene node]]; Also remember to import your SplashScene.h file in order for the project to properly compile. Finally, we have to create the MainMenuScene, which is the scene the Director will run after the last image has faded out. So, let's create that one and leave it blank for now. The following is the MainMenuScene.h file: #import <Foundation/Foundation.h>#import "cocos2d.h"@interface MainMenuScene : CCScene { }@end@interface MainMenuLayer : CCLayer { }@end The following is the MainMenuScene.m file: #import "MainMenuScene.h"@implementation MainMenuScene- (id) init{ self = [super init]; if (self != nil) { [self addChild:[MainMenuLayer node]]; } return self;}-(void)dealloc{ [super dealloc];}@end@implementation MainMenuLayer- (id) init{ if ((self = [super init])) { isTouchEnabled = YES; } return self;}-(void)dealloc{ [super dealloc];}@end That would be all for now. Run the project and you should see the first image appear. Then fade to the next one after a while and continue till the last one. Once the last one has faded out, we move on to the MainMenuScene. What just happened? Creating a new scene is as easy as that. You can see from the MainMenuScene code that what we are doing is quite simple; when the MainMenuScene gets created we just instantiate the MainMenuLayer and add it to the scene. That layer is where we will later add all the necessary logic for the main menu. The MainMenuScene as well as the SplashScene both inherit from the CCScene class. This class is just another CCNode. Let's take a little look at the logic behind the SplashScene: NSMutableArray * splashImages = [[NSMutableArray alloc]init];for(int i =1;i<=3;i++){ CCSprite * splashImage = [CCSprite spriteWithFile:[NSString stringWithFormat:@"splash%d.png",i]]; [splashImage setPosition:ccp(240,160)]; [self addChild:splashImage]; if(i!=1) [splashImage setOpacity:0]; [splashImages addObject:splashImage];} [self fadeAndShow:splashImages]; This piece of code is from the SplashLayer init method. What we are doing here is creating an array that will hold any amount of sprites (in this case, three of them). Then we create and add those sprites to it. Finally, the fadeAndShow method is called, passing that newly created array to it. The fadeAndShow method is responsible for fading the images it has. It grabs the first image in the array (after that, the sprite is removed from the array). It then grabs the next one. Then it applies actions to both of them to fade them in and out. The last action of the second sprite's action is a CCCallFuncND, which we use to call the fadeAndShow method again with the modified array. This occurs if there is more than one remaining sprite in the array. If there isn't, the fadeAndShow method calls the Director's replaceScene method with the MainMenuScene. I have made the SplashLayer logic, so you can add more splash images to the array (or leave just one) if you like. Generally, just one or two images will be more than enough.
Read more
  • 0
  • 0
  • 9208

article-image-designing-objects-3d-printing
Packt
15 Nov 2013
9 min read
Save for later

Designing Objects for 3D Printing

Packt
15 Nov 2013
9 min read
(For more resources related to this topic, see here.) How a 3D printer works A 3D printer needs to take a description of a three-dimensional object and turn it into a physical object. Like Blender, a 3D printer uses values along the X, Y, and Z axes to determine the shape of an object. But where Blender sees an object as perhaps cylinders, spheres, cubes, or edges and faces, a 3D printer is all about layers and perimeters. First, a slicing program opens the object file that you made and it slices the object into vertical layers as seen in the following screenshot: Then, each layer is printed out one by one in a growing stack as seen in the following screenshot: But you can get a better idea of how these layers stack up if you can see it interactively. I have provided an interactive illustration that allows you to see the dragon slice by slice. Scrolling through the frames, you can see how the walls of the dragon's body are built: Open up 4597OS_01_LayersDisplay.blendin your download packet. Examine the thickness of the body at each layer. Press Alt + A to play the animation. Press Esc to stop playing it. You can also drag the current time indicator in the timeline back and forth to look at individual frames, or use the right and left arrow keys. Note how the dragon starts as a series of islands. Look at the dragon's hands. The fingers start off floating in space until they are joined to the arms. The exact method a 3D printer uses to print a layer varies. Some printers work like a pencil, drawing an outline of the shape on that layer and then filling in the shape with cross-hatching. Look at the left side of the preceding screenshot again. The printer would first outline the tail, then fill it in. Next, it would move to one haunch, outline it, and fill it in, and then the other. And finally, it would outline and fill each foot. You can get a better idea of how this happens with this 3D printer's hot end simulator. The hot end is the printer's nozzle where the 3D printing material is extruded. Other printers may use a print head much like an inkjet printer. The print head moves across the printing bed and deposits material where needed. Types of 3D printers So what kinds of printers are there? How do they print and how are they different? The terminology is still a bit confusing. The American Society for Testing and Materials (ASTM International) recently came up with the following categories: Material extrusion is also known as Molten Polymer Deposition (MPD), Fused Deposition Modeling (FDM), or Fused Filament Fabrication (FFF); these extrude a gooey material out in layers to build up the proper shape. This is the class of printers that includes most hobbyist 3D printers. They work like the simulator you just used. These can use plastic, metal wire, wax, sugar, frosting, chocolate, cookie dough pasta, pizza, and even corn chips. Material jetting is also known as photopolymer jetting. Like an inkjet, this printer squirts liquid photopolymers at the right moment, which are cured immediately with ultraviolet light, layer by layer. The object being built is supported by a layer of gel that is also applied by the print head, so overhang is not a problem. Binder jetting uses a two part system. A thin layer of composite material is spread across the print bed. Then, an inkjet-like printing head sprays a binder fluid and possibly colored ink, which combine with the composite material to produce solid colored and sometimes textured objects. This can be plastic, gypsum, or metals, such as copper, tungsten, bronze, and stainless steel. For metals, a second step is needed to make them solid. The binder is removed and metal is infused where the binder used to be. Sheet lamination printers may use materials, such as paper or metal, and will color, cut out, and glue layers together into objects. Vat photopolymerization is also called Stereolithography (SLA). Photopolymerization printers use light to cure liquid material into the right shape. This process uses resins, wax, or liquid plastics for the material. It may use a laser or a high resolution DLP video projector similar to one you would hook up to your computer to give a PowerPoint presentation. Powder bed fusion is also known as Granular Materials Binding. These printers use a laser or heat to fuse layers of powder into the right shape. These can use metal, ceramic, gypsum, or plastic powder. There are several subtypes of powder bed fusion printers. Selective Laser Sintering (SLS) is used with thermoplastics, wax, and ceramic powders. A thin coat of powder is spread across the printing bed. Then, the printing head prints the layer by fusing selected areas with the laser. The printing bed then drops down. Another coat of powder is added and the laser prints the next layer. Selective heat sintering (SHS) uses heat instead of a laser and can be used with thermoplastic powder. Direct Metal Laser Sintering (DMLS) or Selective Laser Melting (SLM) is a subcategory of selective laser sintering. The laser beam melts the metal and makes solid parts with metal alloys like aluminum, iron, stainless steel, maraging steel, nickel, chromium, cobalt, and titanium alloys. In theory, it can be used with most alloys. Directed energy deposition, also known as Electron Beam Melting (EBM), is similar to SLS, but uses an electron beam instead of a laser. The high heat generated by the electron beam allows use of pure metal powder such as titanium alloys, and can make high-detail, high-strength objects that do not need any postmanufacturing heat treatment. Question: Earlier, I mentioned a company named Made In Space, which is making a 3D printer to be used in zero gravity. What kind of printer is it making? Directed energy deposition Vat photopolymerization Material extrusion Powder bed fusion Answer: Option 3, material extrusion is correct. Extruding a material avoids liquid or powder floating around in zero gravity. Basic parts of a 3D printer As you have observed, there are a wide variety of 3D printers. But there are some parts they all have in common. The printing bed is what the 3D object is built upon. The printing head holds the laser, the printing jet, or the hot end of the extruder. And then there are controls to position the printing bed and the printing head in relation to each other; one control for the X dimension, one for the Y dimension, and one for the Z dimension. There are no hard and fast rules for which controls the printing bed and printing head have. The Cube printing head is controlled in the X dimension only and the printing bed is controlled in the Y and Z dimensions, whereas the MendelMaxPro puts X and Z controls on the printer head and controls the printing bed only in the Y dimension. How is a 3D printer controlled? Generally, the answer is stepper motors. Stepper motors are motors that move in small discrete angles of rotation instead of spinning like most regular motors. This allows you to make definite, easily repeatable motions. It is also one reason why there are minimum sizes on the detail that you can make. A 3D printer can't make detail smaller than one step of the stepper motor. Then, through wires, drums, gears, and threaded rods, the motion of the stepper motor is scaled to fit the medium that the printer uses. A hobbyist printer that uses a filament of the ABS or PLA plastic that feeds off of a reel will provide the kind of detail that those plastics can support. A high-end stereolithography printer may get much finer detail. The next graphic is a diagram of the insides of a stepper motor. The rotor is in the center. It rotates and is attached to a shaft that pokes out of the motor. The stators are attached to the outer shell of the motor. They are wrapped with copper wire and an electrical current is run through the wire to give each stator a negative charge, a positive charge, or no charge as indicated in the next graphic. In the graphic, red represents a positive charge, the blue is a negative charge, and the grey has no charge. The rotor in the center has 50 teeth. The stators around the outside have a total of 48 teeth. It's this imbalance in the number of teeth that allow the stepper motor's rotor to walk around step-by-step. The positive charge of the rotor is attracted to the stator teeth that are negatively charged. In the following screenshot, you can see that the rotor teeth aren't well aligned with the uncharged stator that is counter-clockwise from the blue stator. To do a single step, the stepper motor controller changes the negative charge from the blue stator in the following screenshot to the stator just counter-clockwise to it. Then, the teeth in the rotor try to align with that stator. So, the rotor moves just a little, a step. To continue moving more steps, the stator with the negative charge keeps moving to the next stator, as follows: The stepper motor is then attached to a control belt or a shaft with a screw thread to give the printer precise control of the print head and the printing bed. There may be one or more stepper motors controlling a single axis. Summary In this article, we covered the fundamentals of how a 3D printer works and the different kinds of printers that there are. And you discovered that 3D printers can handle a wide variety of materials from wood, to plastic, to titanium. We also covered how to control a 3D printer by a stepper motor. Resources for Article: Further resources on this subject: Introduction to the Editing Operators in Blender: A Sequel [Article] Getting Started with Blender’s Particle System [Article] Blender 3D: Interview with Allan Brito [Article]
Read more
  • 0
  • 0
  • 9207

article-image-cryengine-3-terrain-sculpting
Packt
21 Jun 2011
11 min read
Save for later

CryENGINE 3: Terrain Sculpting

Packt
21 Jun 2011
11 min read
CryENGINE 3 Cookbook Over 100 recipes written by Crytek developers for creating AAA games using the technology that created Crysis 2 Creating a new level Before we can do anything with the gameplay of the project that you are creating, we first need a foundation of a new level for the player to stand on. This recipe will cover how to create a new level from scratch. Getting ready Before we begin, you must have Sandbox 3 open. How to do it... At any point, with Sandbox open, you may create a new level by following these steps: Click File (found in the top -left of the Sandbox's main toolbar). Click New. From here, you will see a new dialog screen that will prompt you for information on how you want to set up your level. The most important aspect of a level is naming it, as you will not be able to create a level without some sort of proper name for the level's directory and its .cry file. You may name your level anything you wish, but for the ease of instruction we shall refer to this level as My_Level: In the Level Name dialog box, type in My_Level. For the Terrain properties, use the following values: Use Custom Terrain Size: True Heightmap Resolution:512x512 Meters Per Unit: 1 Click OK. Depending on your system specifications, you may find that creating a new level will require anywhere from a few seconds to a couple of minutes. Once finished, the Viewport should display a clear blue sky with the dialog in your console reading the following three lines: Finished synchronous pre-cache of render meshes for 0 CGF's Finished pre-caching camera position (1024,1024,100) in 0.0 sec Spawn player for channel 1 This means that the new level was created successfully. How it works... Let's take a closer look at each of the options used while creating this new level. Using the Terrain option This option allows the developer to control whether to have any terrain on the level to be manipulated by a heightmap or not. Sometimes terrain can be expensive for levels and if any of your future levels contain only interiors or only placed objects for the player to navigate on, then setting this value to false will be a good choice for you and will save a tremendous amount of memory and aid in the performance of the level later on. Heightmap resolution This drop-down controls the resolution of the heightmap and the base size of the play area defined. The settings can range from the smallest resolution (128 x 128) all the way up to the largest supported resolution (8192 x 8192). Meters per unit If the Heightmap Resolution is looked at in terms of pixel size, then this dialog box can also be viewed as the Meters Per Pixel. This means that each pixel of the heightmap will be represented by these many meters. For example, if a heightmap's resolution has 4 Meters Per Unit (or Pixel), then each pixel on the generated heightmap will measure four meters in length and width on the level. Even though this Meters Per Unit can be used to increase the size of your level, it will decrease the fidelity of the heightmap. You will notice that attempting to smoothen out the terrain may be difficult as there will be a wider minimum triangle size set by this value. Terrain size This is the resulting size of the level with the equation of (Heightmap Resolution) x (Meters Per unit). Here are some examples of the results you will see (m = meters): (128x128) x 4m = 512x512m (512x512) x 16m = 8192x8192m (1024x1024) x 2m = 2048x2048m There's more... If you need to change your unit size after creating the map, you may change it by going into the Terrain Editor | Modify | Set Unit Size. This will allow you to change the original Meters Per Unit to the size you want it to be.   Generating a procedural terrain This recipe deals with the procedural generation of a terrain. Although never good enough for a final product because you will want to fine tune the heightmap to your specifications, these generated terrains are a great starting point for anyone new to creating levels or for anyone who needs to set up a test level with the Sandbox. Different heightmap seeds and a couple of tweaks to the height of the level and you can generate basic mountain ranges or islands quickly that are instantly ready to use. Getting ready Have My_Level open inside of Sandbox. How to do it... Up at the top-middle of the Sandbox main toolbar, you will find a menu selection called Terrain. From there you should see a list of options, but for now you will want to click on Edit Terrain. This opens the Terrain Editor window. The Terrain Editor window has a multitude of options that can be used to manipulate the heightmap in your level. But first we want to set up a basic generated heightmap for us to build a simple map with. Before we generate anything, we should first set the maximum height of the map to something more manageable. Follow these steps: Click Modify. Then click Set Max Height. Set your Max Terrain Height to 256 (these units are in meters). Now, we may be able to generate the terrain: Click Tools. Then click Generate Terrain. Modify the Variation (Random Base) to the value of 15. Click OK. After generating, you should be able to see a heightmap similar to the following screenshot: This is a good time to generate surface texture (File | Generate surface texture | OK), which allows you to see the heightmap with a basic texture in the Perspective View. How it works... The Maximum Height value is important as it governs the maximum height at which you can raise your terrain to. This does not mean that it is the maximum height of your level entirely, as you are still able to place objects well above this value. It is also important to note that if you import a grey scale heightmap into CryENGINE then this value will be used as the upper extreme of the heightmap (255,255,255 white) and the lower extreme will always be at 0 (0,0,0 black). Therefore the heightmap will be generated within 0 m height and the maximum height. Problems such as the following are a common occurrence: Tall spikes are everywhere on the map or there are massive mountains and steep slopes: Solution: Reduce the Maximum Height to a value that is more suited to the mountains and slopes you want The map is very flat and has no hills or anything from my heightmap: Solution: Increase the Maximum Height to a value that is suitable for making the hills you want There's more... Here are some other settings you might choose to use while generating the terrain. Terrain generation settings The following are the settings to generate a procedural terrain: Feature Size: This value handles the general height manipulations within the seed and the size of each mound within the seed. As the size of the feature depends greatly on rounded numbers it is easy to end up with a perfectly rounded island, therefore it is best to leave this value at 7.0. Bumpiness / Noise (Fade): Basically, this is a noise filter for the level. The greater the value, the more noise will appear on the heightmap. Detail (Passes): This value controls how detailed the slopes will become. By default, this value is very high to see the individual bumps on the slopes to give a better impression of a rougher surface. Reducing this value will decrease the amount of detail/roughness in the slopes seen. Variation: This controls the seed number used in the overall generation of the Terrain Heightmap. There are a total of 33 seeds ranging from 0 – 32 to choose from as a starting base for a basic heightmap. Blurring (Blur Passes): This is a Blur filter. The higher the amount, the smoother the slopes will be on your heightmap. Set Water Level: From the Terrain Editor window, you can adjust the water level from Modify | Set Water Level. This value changes the base height of the ocean level (in meters). Make Isle: This tool allows you to take the heightmap from your level and automatically lowers the border areas around the map to create an island. From the Terrain Editor window, select Modify | Make Isle.   Navigating a level with the Sandbox Camera The ability to intuitively navigate levels is a basic skill that all developers should be familiar with. Thankfully, this interface is quite intuitive to anyone who is already familiar with the WASD control scheme popular in most First Person Shooters Games developed on the PC. Getting ready You should have already opened a level from the CryENGINE 3 Software Development Kit content and seen a perspective viewport displaying the level. The window where you can see the level is called the Perspective Viewport window. It is used as the main window to view and navigate your level. This is where a large majority of your level will be created and common tasks such as object placement, terrain editing, and in-editor play testing will be performed. How to do it... The first step to interacting with the loaded level is to practice moving in the Perspective Viewport window. Sandbox is designed to be ergonomic for both left and right-handed users. In this example, we use the WASD control scheme, but the arrow keys are also supported for movement of the camera. Press W to move forwards. Then press S to move backwards. A is pressed to move or strafe left. Finally, D is pressed to move or strafe right. Now you have learned to move the camera on its main axes, it's time to adjust the rotation of the camera. When the viewport is the active window, hold down the right mouse button on your mouse and move the mouse pointer to turn the view. You can also hold down the middle mouse button and move the mouse pointer to pan the view. Roll the middle mouse button wheel to move the view forward or backward. Finally, you can hold down Shift to double the speed of the viewport movements. How it works... The Viewport allows for a huge diversity of views and layouts for you to view your level; the perspective view is just one of many. The perspective view is commonly used as it displays the output of the render engine. It also presents you a view of your level using the standard camera perspective, showing all level geometry, lighting, and effects. To experiment further with the viewport, note that it can also render subsystems and their toolsets such as flow graph, or character editor. There's more... You will likely want to adjust the movement speed and how to customize the viewport to your individual use. You can also split the viewport in multiple different views, which is discussed further. Viewport movement speed control The Speed input is used to increase or decrease the movement speed of all the movements you make in the main Perspective Viewport. The three buttons to the right of the Speed: inputs are quick links to the .1, 1, and 10 speeds. Under Views you can adjust the viewport to view different aspects of your level Top View, Front, and Left views will show their respective aspects of your level, consisting of bounding boxes and line-based helpers. It should be noted that geometry is not drawn. Map view shows an overhead map of your level with helper, terrain, and texture information pertaining to your level. Splitting the main viewport to several subviewports Individual users can customize the layout and set viewing options specific to their needs using the viewport menu accessed by right-clicking on the viewports header. The Layout Configuration window can be opened from the viewport header under Configure Layout. Once selected, you will be able to select one of the preset configurations to arrange the windows of the Sandbox editor into multiple viewport configurations. It should be recognized that in multiple viewport configurations some rendering effects may be disabled or performance may be reduced.  
Read more
  • 0
  • 0
  • 9207
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-configuring-and-deploying-ejb-30-entity-weblogic-server
Packt
27 Aug 2010
8 min read
Save for later

Configuring and Deploying the EJB 3.0 Entity in WebLogic Server

Packt
27 Aug 2010
8 min read
(For more resources on Oracle, see here.) Creating a Persistence Configuration file An EJB 3.0 entity bean is required to have a persistence.xml configuration file, which defines the database persistence properties. A persistence.xml file gets added to the META-INF folder when a JPA project is defined. Copy the following listing to the persistence.xml file in Eclipse: <?xml version="1.0" encoding="UTF-8" ?> <persistence xsi_schemaLocation= "http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd" version="1.0"> <persistence-unit name="em"> <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider> <jta-data-source>jdbc/MySQLDS</jta-data-source> <class>ejb3.Catalog</class> <properties> <property name="eclipselink.target-server" value="WebLogic_10" /> <property name="javax.persistence.jtaDataSource" value="jdbc/ MySQLDS" /> <property name="eclipselink.ddl-generation" value="create-tables" /> <property name="eclipselink.target-database" value="MySQL" /> </properties> </persistence-unit> </persistence> The persistence-unit is required to be named and may be given any name. We had configured a JDBC data source with JNDI jdbc/MySQLDS in WebLogic Server. Specify the JNDI name in the jta-data-source element. The properties element specifies vendor-specific properties. The eclipselink.ddl-generation property is set to create-tables, which implies that the required database tables will be created unless they are already created . The persistence.xml configuration file is shown in the Eclipse project in the following illustration: (Move the mouse over the image to enlarge.) Creating a session bean For better performance, one of the best practices in developing EJBs is to access entity beans from session beans. Wrapping an entity bean with a session bean reduces the number of remote method calls as a session bean may invoke an entity bean locally. If a client accesses an entity bean directly, each method invocation is a remote method call and incurs an overhead of additional network resources. We shall use a stateless session bean, which consumes less resources than a stateful session bean, to invoke entity bean methods. In this section, we create a session bean in Eclipse. A stateless session bean class is just a Java class annotated with the @Stateless annotation. Therefore, we create Java classes for the session bean and session bean remote interface in Eclipse. To create a Java class, select File | New. In the New window, select Java | Class and click on Next> In the New Java Class window, select the Source folder as EJB3JPA/src, EJB3JPA being the project name. Specify Class Name as CatalogTestBean and click on Finish. Similarly, create a CatalogTestBeanRemote interface by selecting Java | Interface in the New window. The session bean class and the remote interface get added to the EJB3JPA project. The session bean class The stateless session bean class, CatalogTestBean implements the CatalogTestRemote interface. We shall use the EntityManager API to create, find, query, and remove entity instances. Inject an EntityManager using the @PersistenceContext annotation. Specify unitName as the same as the persistence-unit name in the persistence.xml configuration file: @PersistenceContext(unitName = "em") EntityManager em; Next, create a test() method, which we shall invoke from a test client. In the test() method we shall create and persist entity instances, query an entity instance, and delete an entity instance, all using an EntityManager object, which we had injected earlier in the session bean class. Injecting an EntityManager implies that an instance of EntityManager is made available to the session bean. Create an instance of the Entity bean class: Catalog catalog = new Catalog(new Integer(1), "Oracle Magazine", "Oracle Publishing", "September-October 2009", "Put Your Arrays in a Bind","Mark Williams"); Persist the entity instance to the database using the persist() method: em.persist(catalog); Similarly, persist two more entity instances. Next, create a query using the createQuery() method of the EntityManager object. The query string may be specified as a EJB-QL query. Unlike HQL, the SELECT clause is not optional in EJB-QL. Execute the query and return the query result as a List using the getResultList() method. As an example, select the catalog entry corresponding to author David Baum. The FROM clause of a query is directed towards the mapped entity bean class, not the underlying database. List catalogEntry =em.createQuery("SELECT c from Catalog c where c.author=:name").setParameter("name","David Baum"). getResultList(); Iterate over the result list to output the properties of the entity instance: for (Iterator iter = catalogEntry.iterator(); iter.hasNext(); ) { Catalog element = (Catalog)iter.next(); retValue =retValue + "<br/>" + element.getJournal() + "<br/>" + element.getPublisher() +"<br/>" + element.getDate() + "<br/>" + element.getTitle() + "<br/>" + element.getAuthor() +"<br/>"; } The variable retValue is a String that is returned by the test() method. Similarly, create and run a EJB-QL query to return all titles in the Catalog database: List allTitles =em.createQuery("SELECT c from Catalog c"). getResultList(); An entity instance may be removed using the remove() method: em.remove(catalog2); The corresponding database row gets deleted from the Catalog table. Subsequently, create and run a query to list all the entity instances mapped to the database. The session bean class, CatalogTestBean, is listed next: package ejb3; import java.util.Iterator; import java.util.List; import javax.ejb.Stateless; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; /** * Session Bean implementation class CatalogTestBean */ @Stateless(mappedName = "EJB3-SessionEJB") public class CatalogTestBean implements CatalogTestBeanRemote { @PersistenceContext(unitName = "em") EntityManager em; /** * Default constructor. */ public CatalogTestBean() { // TODO Auto-generated constructor stub } public String test() { Catalog catalog = new Catalog(new Integer(1), "Oracle Magazine", "Oracle Publishing", "September-October 2009", "Put Your Arrays in a Bind","Mark Williams"); em.persist(catalog); Catalog catalog2 = new Catalog(new Integer(2), "Oracle Magazine", "Oracle Publishing", "September-October 2009", "Oracle Fusion Middleware 11g: The Foundation for Innovation", "David Baum"); em.persist(catalog2); Catalog catalog3 = new Catalog(new Integer(3), "Oracle Magazine", "Oracle Publishing", "September-October 2009", "Integrating Information","David Baum"); em.persist(catalog3); String retValue = "<b>Catalog Entries: </b>"; List catalogEntry = em.createQuery("SELECT c from Catalog c where c.author=:name").setParameter("name", "David Baum").getResultList(); for (Iterator iter = catalogEntry.iterator(); iter.hasNext(); ) { Catalog element = (Catalog)iter.next(); retValue = retValue + "<br/>" + element.getJournal() + "<br/>" + element.getPublisher() + "<br/>" + element.getDate() + "<br/>" + element.getTitle() + "<br/>" + element.getAuthor() + "<br/>"; } retValue = retValue + "<b>All Titles: </b>"; List allTitles = em.createQuery("SELECT c from Catalog c").getResultList(); for (Iterator iter = allTitles.iterator(); iter.hasNext(); ) { Catalog element = (Catalog)iter.next(); retValue = retValue + "<br/>" + element.getTitle() + "<br/>"; } em.remove(catalog2); ); retValue = retValue + "<b>All Entries after removing an entry: </b>"; List allCatalogEntries = em.createQuery("SELECT c from Catalog c"). getResultList(); for (Iterator iter = allCatalogEntries.iterator(); iter.hasNext(); ) { Catalog element = (Catalog)iter.next(); retValue = retValue + "<br/>" + element + "<br/>"; } return retValue; } } We also need to add a remote or a local interface for the session bean: package ejb3; import javax.ejb.Remote; @Remote public interface CatalogTestBeanRemote { public String test(); } The session bean class and the remote interface are shown next: We shall be packaging the entity bean and the session bean in a EJB JAR file, and packaging the JAR file with a WAR file for the EJB 3.0 client into an EAR file as shown next: EAR File | | |-WAR File | |-EJB 3.0 Client |-JAR File | |-EJB 3.0 Entity Bean EJB 3.0 Session Bean Next, we create an application.xml for the EAR file. Create a META-INF folder for the application.xml. Right-click on the EJB3JPA project in Project Explorer and select New>Folder. In the New Folder window, select the EJB3JPA folder and specify the new Folder name as META-INF. Click on Finish. Right-click on the META-INF folder and select New | Other. In the New window, select XML | XML and click on Next. In the New XML File window, select the META-INF folder and specify File name as application.xml. Click on Next. Click on Finish. An application.xml file gets created. Copy the following listing to application.xml: <?xml version = '1.0' encoding = 'windows-1252'?> <application> <display-name></display-name> <module> <ejb>ejb3.jar</ejb> </module> <module> <web> <web-uri>weblogic.war</web-uri> <context-root>weblogic</context-root> </web> </module> </application> The application.xml in the Project Explorer is shown next:
Read more
  • 0
  • 3
  • 9206

article-image-active-directory-design-principles-part-1-2
Packt
30 Sep 2009
10 min read
Save for later

Active Directory Design Principles: Part 1

Packt
30 Sep 2009
10 min read
The one thing to keep in mind is that when designing your Active Directory, never go at it from a, present needs, point of view. Technology and systems are changing so fast nowadays that you have to design with the most open and future-proof concept that you can think of. It was only a few years back when Windows 95 revolutionized the personal computing platform by pushing 32-bit addressing to the mainstream. Before that it was 14 years where everyone ran 16-bit programs on 16- or 32-bit processors. In April 2003, Microsoft launched the 64-bit version of its Server Operating System and in April 2005, the 64-bit version of its Desktop Operating System, Windows XP. These are less then a decade after the big Windows 95 push. Active Directory was introduced with Windows 2000, which is only Five years after Windows NT 4's "enhanced omain structure". The trend is that new features and new technologies are constantly being invented and introduced. While there are quite a few companies that have a proper open and flexible design in their Active Directory structures, there are a lot more organizations that see Active Directory as the answer to all their prayers and just keep adding things to it and to the schema. To read more about the technical aspects of the AD schema, please refer to http://msdn2.microsoft.com/en-us/library/ms675085.aspx. Software companies nowadays are pushing "Active Directory compatible" features more and more, and problems can arise when these packages need complete domain administrator rights in order to function (or modify the Active Directories' inner workings), which they usually do not advertise up-front. The need for proper planning and design of the AD is extremely high in order to ensure that your DR strategies will work and are easy to implement. A properly designed AD is extremely resilient and still very flexible. Whenever you intend to add new services, make sure that you test and re-test the things that are necessary for the service to function properly. As the IT department, you are responsible to keep the systems going and ensure business continuity. Active Directory elements When designing an Active Directory, you need to be completely clear of what each element or part actually means and how it fits into the overall design. The old saying goes: You can't see the forest because of the trees, and you can apply this to Active Directory as well. It is all about trees and forests and leaves and branches. The Active Directory forest The forest, in terms of Active Directory, basically means every domain, organizational unit, and any other object stored within its database. The forest is the absolute top level of your Active Directory infrastructure. Of course, you can have more than one forest in a company, which actually represent security boundaries, and can therefore improve security between different business units or companies belonging to a single organization. The point behind the forest is that you have all your domains and domain tree within your organization contained within it. It is designed so that you can have transitive trust-links between all of the trees within one forest. To read more about the technical layout of AD, please read Domains and Forests Technical Reference at: http://technet2.microsoft.com/windowsserver/en/library/16a2bdb3-d0a3-4435-95fd-50116e300c571033.mspx. To visualize a forest with its parts, please see the following image. The Active Directory tree A tree in Active Directory refers to a domain and all of its objects that adhere to a single DNS name. For example, a tree of nailcorp.com would contain all other domains that end with "nailcorp.com". So, americas.nailcorp.com, europe.nailcorp.com, and asia.nailcorp.com all belong to the Active Directory tree of nailcorp.com. You cannot separate these unless you create a whole new forest for a sub-domain. Organizational Units and Leaf Objects In Active Directory, Organizational Units (OU), which are also called Containers, and Leaf Objects, which are non-containing objects such as computer accounts and user accounts, are directly related and even though you could have objects that do not belong to an OU, it isn't recommended and isn't really feasible. Organizational Units are comparable to folders in a filing cabinet, and objects are the files. You can move files between different folders, and classifications or properties are applied to the files within a folder. For example, if you move a file into a folder classified "Top Secret", the file will automatically fall under that classification. The same applies to objects within an OU, all properties or rules that apply to the OU apply to the objects within it. OUs, however, are mostly useful from an administrative point of view, not from an user's point of view. If you think of how your files are organized, for example, on your computer, they are most likely to be organized into different folders. You can go ahead and set different folder settings, such as permissions, and it will affect all of the files within that folder, but anything outside that folder won't have its permission affected. It is exactly the same principle with OUs. Any OU that will be created within an OU will contain all of the policy settings of the parent unless you change them. An object can also only belong to a single OU, just as a single file can only be contained within a single folder. Leaf objects in Active Directory can be users, contacts, and computers. Or in short, any object that cannot contain other objects. They are called leaf objects because they are like leaves on a tree. And, as you can guess, they are the "lowest" class of objects within Active Directory. But if you now look at the forest-tree-branch-leaf concept, it is starting to make sense. You can access the OUs and other objects through the Microsoft Management Console (MMC) or through the Users and Computers tool in the Administrative Tools. This second option actually just invokes the MMC with the correct view and is a lot quicker, as seen in the following screenshot: Active Directory Sites The Sites and Services MMC snap-in is a utility that a lot of Windows administrators, particularly in smaller organizations, completely overlook. This part of Active Directory, however, is one of the most crucial parts to understand and implement correctly. If you have several locations in your organization, you need to know about Active Directory Sites. Sites give you a very unique and well-designed approach to separate specific locations within your Active Directory. As the principle of an Active Directory domain is global-meaning that it is meant to be the same anywhere-it could present a problem for users who move from office to office, or for offices with network connections that are slow. Active Directory sites allow you to specify the IP address spaces or subnets used within your organization and, therefore, bring the structure of your network into Active Directory. The usefulness of having properly organized and maintained Sites becomes more evident when you consider that any machine within an address space will use that Sites' DC to authenticate. This is a great feature of AD and reduces unnecessary traffic. However, it requires having Sites and subnets properly updated and maintained. This is also particularly useful for defining different replication schedules for different locations within the same domain, and also to support users who travel. Once they log on through the other location, they are assigned an IP address from that network. The Windows locator service will then look up which DC is the nearest one, and the user won't log on all the way to their usual DC (to read more about how the locator service works please refer to http://support.microsoft.com/kb/314861). This saves bandwidth and speeds up the authentication process. Bandwidth nowadays is cheap, especially in developed countries such as the USA or most parts of Western Europe. But just because it is cheap in some parts, does not mean it is cheap in other parts of your organization. If you are primarily located within developed countries, but your then company decides to open 10 or 20 small sales offices within not-so-developed countries, where bandwidth is expensive, then you really need to start using AD sites. Of course, the problem then is that because you haven't used AD sites before, you need to make the appropriate changes to your infrastructure to accommodate them, and train staff appropriately in order to be able to implement, support, and manage them. In this example, the argument might be brought up that each of these small branch offices has a local DC that also functions as a File and Print server where the local employees collaborate. This is great, but what about replication to and from your Hub site? Which is the data centre that hosts a critical part of your Active Directory backend? If changes to your AD are fairly frequent, for example, adding and removing users on a regular basis, then the Active Directory will replicate—if the Site links are properly configured—without compression every 15 minutes. Of course, depending on the size of your organization, this can be quite a strain on the link you have from that office. If the people at that office receive email and browse the Web over the same link, network performance will degrade significantly for users and cause unnecessary inconvenience. To see what Sites look like in the Active Directory Sites and Services console, see the following screenshot: Group Policy Objects Group Policy Objects in Active Directory are a set of defined rules for settings about the user environment or the operating environment for a particular PC. They are treated as standalone objects because they can be linked to different OUs. This gives you the flexibility of creating one set of rules and applying it to different OUs in different OU structures, making settings deployment much easier and administratively quick. The policy settings are quite extensive and if you want to get your hands dirty, you can create your own policy templates, giving you even more control over the machines and application settings located in your domain. There are templates available for many settings, ready to use. The templates for these settings are called ADM templates and there are quite a few already included in the Windows 2003 installation. Some applications, such as Microsoft Office 2007, also provide ADM templates that can be loaded and modified (see http://www.microsoft.com/downloads/details.aspx?displaylang=en&FamilyID=92d8519a-e143-4aee-8f7a-e4bbaeba13e7 for Office 2007 ADM templates). Using ADM templates, you do not need to write anything by yourself, and so it is a quicker way apply to GPO settings. The following screenshot shows Office 2007 ADM templates loaded in the Group Policy Editor.
Read more
  • 0
  • 0
  • 9204

article-image-exchange-management-shell-common-tasks
Packt
21 Feb 2018
11 min read
Save for later

Exchange Management Shell Common Tasks

Packt
21 Feb 2018
11 min read
In this article by Jonas Andersson, Nuno Mota, Michael Pfeiffer, the author of the book Microsoft Exchange Server 2016 PowerShell Cookbook, they will cover: Manually configuring remote PowerShell connections Using explicit credentials with PowerShell cmdlets (For more resources related to this topic, see here.) Microsoft introduced some radical architectural changes in Exchange 2007, including a brand-new set of management tools. PowerShell, along with an additional set of Exchange Server specific cmdlets, finally gave administrators an interface that could be used to manage the entire product from a command line shell. This was an interesting move, and at that time the entire graphical management console was built on top of this technology. The same architecture still existed with Exchange 2010, and PowerShell was even more tightly integrated with this product. Exchange 2010 used PowerShell v2, which relied heavily on its new remoting infrastructure. This provides seamless administrative capabilities from a single seat with the Exchange Management Tools, whether your servers are on-premises or in the cloud. Initially when Exchange 2013 was released, it was using version 4 of PowerShell, and during the life cycle it could be updated to version 5 of PowerShell with a lot of new cmdlets, core functionality changes, and even more integrations with the cloud services. Now with Exchange 2016, we have even more cmdlets and even more integrations with cloud-related integration and services. During the initial work on this book, we had 839 cmdlets with Cumulative Update 4 which was released in December 2016. This can be compared with the previous book, where at that stage we had 806 cmdlets based on Service Pack 1 and Cumulative Update 7. It gives us an impression that Microsoft is working heavily on the integrations and that the development of the on-premises product is still ongoing. This demonstrates that more features and functionality have been added over time. It will most likely continue like this in the future as well. In this article, we'll cover some of the most common topics, as well as common tasks, that will allow you to effectively write scripts with this latest release. We'll also take a look at some general tasks such as scheduling scripts, sending emails, generating reports, and more. Performing some basic steps To work with the code samples in this article, follow these steps to launch the Exchange Management Shell: Log onto a workstation or server with the Exchange Management Tools installed. You can connect using remote PowerShell if, for some reason, you don't have Exchange Management Tools installed. Use the following command: $Session = New-PSSession -ConfigurationName Microsoft.Exchange ` -ConnectionUri http://tlex01/PowerShell/ ` -Authentication Kerberos Import-PSSession $Session Open the Exchange Management Shell by clicking the Windows button and go to Microsoft Exchange Server 2016 | Exchange Management Shell. Remember to start the Exchange Management Shell using Run as Administrator to avoid permission problems. In the article, notice that in the examples of cmdlets, I have used the back tick (`) character for breaking up long commands into multiple lines. The purpose of this is to make it easier to read. The back ticks are not required and should only be used if needed. Notice that the Exchange variables, such as $exscripts, are not available when using the preceding method. Manually configuring remote PowerShell connections Just like Exchange 2013, Exchange 2016 is very reliable on remote PowerShell for both on-premises and cloud services. When you double-click the Exchange Management Shell shortcut on a server or workstation with the Exchange Management Tools installed, you are connected to an Exchange server using a remote PowerShell session. PowerShell remoting also allows you to remotely manage your Exchange servers from a workstation or a server even when the Exchange Management Tools are not installed. In this recipe, we'll create a manual remote shell connection to an Exchange server using a standard PowerShell console. Getting ready To complete the steps in this recipe, you'll need to log on to a workstation or a server and launch Windows PowerShell. How to do it... First, create a credential object using the Get-Credential cmdlet. When running this command, you'll be prompted with a Windows authentication dialog box. Enter a username and password for an account that has administrative access to your Exchange organization. Make sure you enter your user name in DOMAINUSERNAME or UPN format: $credential = Get-Credential Next, create a new session object and store it in a variable. In this example, the Exchange server we are connecting to is specified using the -ConnectionUri parameter. Replace the server FQDN in the following example with one of your own Exchange servers: $session = New-PSSession -ConfigurationName Microsoft.Exchange ` -ConnectionUri http://tlex01.testlabs.se/PowerShell/ ` -Credential $credential Finally, import the session object: Import-PSSession $session -AllowClobber After you execute the preceding command, the Exchange Management Shell cmdlets will be imported into your current Windows PowerShell session, as shown in the following screenshot: How it works... Each server runs IIS and supports remote PowerShell sessions through HTTP. Exchange servers host a PowerShell virtual directory in IIS. This contains several modules that perform authentication checks and determine which cmdlets and parameters are assigned to the user making the connection. This happens both when running the Exchange Management Shell with the tools installed, and when creating a manual remote connection. The IIS virtual directory that is being used for connecting is shown in the following screenshot: The IIS virtual directories can also be retrieved by using PowerShell with the cmdlet Get-WebVirtualDirectory. For getting the information about the web applications, use the cmdlet Get-WebApplication. Remote PowerShell connections to Exchange 2016 servers connect almost the same way as Exchange 2013 did. This is called implicit remoting that allows us to import remote commands into the local shell session. With this feature, we can use the Exchange PowerShell cmdlets installed on the Exchange server and load the cmdlets into our local PowerShell session without installing any management tools. However, the detailed behavior for establishing a remote PowerShell session was changed in Exchange 2013 CU11. What happens right now when a user or admin is trying to establish the PowerShell session is that it first tries to connect to the user’s or admin’s mailbox (anchor mailbox), if there are any. If the user doesn’t have an existing mailbox, the PowerShell request will be redirected to the organization arbitration mailbox named SystemMailbox{bb558c35-97f1-4cb9-8ff7-d53741dc928c[AP4] }. You may be curious as to why Exchange uses remote PowerShell even when the tools are installed and when running the shell from the server. There are a couple of reasons for this, but some of the main factors are permissions. The Exchange 2010, 2013, and 2016 permissions model has been completely transformed in these latest versions and uses a feature called Role Based Access Control (RBAC), which defines what administrators can and cannot do. When you make a remote PowerShell connection to an Exchange 2016 server, the RBAC authorization module in IIS determines which cmdlets and parameters you have access to. Once this information is obtained, only the cmdlets and parameters that have been assigned to your account through an RBAC role are loaded into your PowerShell session using implicit remoting. There's more... In the previous example, we explicitly set the credentials used to create the remote shell connection. This is optional and not required if the account you are currently logged on with has the appropriate Exchange permissions assigned. To create a remote shell session using your currently logged on credentials, use the following syntax to create the session object: $session = New-PSSession -ConfigurationName Microsoft.Exchange ` -ConnectionUri http://tlex01.testlabs.se/PowerShell/ Once again, import the session: Import-PSSession $session When the tasks have been completed, remove the session: Remove-PSSession $session You can see here that the commands are almost identical to the previous example, except this time we've removed the -Credential parameter and used the assigned credential object. After this is done, you can simply import the session and the commands will be imported into your current session using implicit remoting. In addition to implicit remoting, Exchange 2016 servers running PowerShell v5 or above can also be managed using fan-out remoting. This is accomplished using the Invoke-Command cmdlet and it allows you to execute a script block on multiple computers in parallel. For more details, run Get-Help Invoke-Command and Get-Help about_remoting. Since Exchange Online is commonly used by Microsoft customers nowadays, let’s take a look at an example on how to connect as well. It’s very similar to connecting to remote PowerShell on-premises. The following prerequisites are required: .NET Framework 4.5 or 4.5.1 and then either Windows Management Framework 3.0 or 4.0. Create a variable of the credentials: $UserCredential = Get-Credential Create a session variable: $session = New-PSSession -ConfigurationName Microsoft.Exchange ` -ConnectionUri https://outlook.office365.com/powershell-liveid/ ` -Credential $UserCredential -Authentication Basic ` -AllowRedirection Finally, import the session: Import-PSSession $session -AllowClobber Perform the tasks you want to do: Get-Mailbox Exchange Online mailboxes are shown in the following screenshot: When the tasks have been completed, remove the session: Remove-PSSession $session Using explicit credentials with PowerShell cmdlets There are several PowerShell and Exchange Management Shell cmdlets that provide a credential parameter that allows you to use an alternate set of credentials when running a command. You may need to use alternate credentials when making manual remote shell connections, sending email messages, working in cross-forest scenarios, and more. In this recipe, we'll take a look at how you can create a credential object that can be used with commands that support the -Credential parameter. How to do it... To create a credential object, we can use the Get-Credential cmdlet. In this example, we store the credential object in a variable that can be used by the Get-Mailbox cmdlet: $credential = Get-Credential Get-Mailbox -Credential $credential How it works... When you run the Get-Credential cmdlet,, you are presented with a Windows authentication dialog box requesting your username and password. In the previous example, we assigned the Get-Credential cmdlet to the $credential variable. After typing your username and password into the authentication dialog box, the credentials are saved as an object that can then be assigned to the -Credential parameter of a cmdlet. The cmdlet that utilizes the credential object will then run using the credentials of the specified user. Supplying credentials to a command doesn't have to be an interactive process. You can programmatically create a credential object within your script without using the Get-Credential cmdlet: $user = "testlabsadministrator" $pass = ConvertTo-SecureString -AsPlainText P@ssw0rd01 -Force $credential = New-Object ` System.Management.Automation.PSCredential ` -ArgumentList $user,$pass You can see here that we've created a credential object from scratch without using the Get-Credential cmdlet. In order to create a credential object, we need to supply the password as a secure string type. The ConvertTo-SecureString cmdlet can be used to create a secure string object. We then use the New-Object cmdlet to create a credential object specifying the desired username and password as arguments. If you need to prompt a user for their credentials but you do not want to invoke the Windows authentication dialog box, you can use this alternative syntax to prompt the user in the shell for their credentials: $user = Read-Host "Please enter your username" $pass = Read-Host "Please enter your password" -AsSecureString $credential = New-Object ` System.Management.Automation.PSCredential-ArgumentList ` $user,$pass This syntax uses the Read-Host cmdlet to prompt the user for both their username and password. Notice that when creating the $pass object, we use Read-Host with the -AsSecureString parameter to ensure that the object is stored as a secure string. There's more... After you've created a credential object, you may need to access the properties of that object to retrieve the username and password. We can access the username and password properties of the $credential object created previously using the following commands: You can see here that we can simply grab the username stored in the object by accessing the UserName property of the credential object. Since the Password property is stored as a secure string, we need to use the GetNetworkCredential method to convert the credential to a NetworkCredential object that exposes the Password property as a simple string. Another powerful method for managing passwords for scripts is to encrypt them and store them into a text file. This can be easily done using the following example. The password is stored into a variable: $secureString = Read-Host -AsSecureString "Enter a secret password" The variable gets converted from SecureString and saved to a text file: $secureString | ConvertFrom-SecureString | Out-File .storedPassword.txt The content in the text file is retrieved and converted into a SecureString value: $secureString = Get-Content .storedPassword.txt | ConvertTo-SecureString Summary In this article, we have covered how to manually setup remote PowerShell connections and how to work with the PowerShell cmdlets. Resources for Article: Further resources on this subject: Exploring Windows PowerShell 5.0 [article] Working with PowerShell [article] How to use PowerShell Web Access to manage Windows Server [article]
Read more
  • 0
  • 0
  • 9201

article-image-querying-and-selecting-data
Packt
17 Apr 2013
13 min read
Save for later

Querying and Selecting Data

Packt
17 Apr 2013
13 min read
(For more resources related to this topic, see here.) Constructing proper attribute query syntax The construction of property attribute queries is critical to your success in creating geoprocessing scripts that query data from feature classes and tables. All attribute queries that you execute against feature classes and tables will need to have the correct SQL syntax and also follow various rules depending upon the datatype that you execute the queries against. Getting ready Creating the syntax for attribute queries is one of the most difficult and time-consuming tasks that you'll need to master when creating Python scripts that incorporate the use of the Select by Attributes tool. These queries are basically SQL statements along with a few idiosyncrasies that you'll need to master. If you already have a good understanding of creating queries in ArcMap or perhaps an experience with creating SQL statements in other programming languages, then this will be a little easier for you. In addition to creating valid SQL statements, you also need to be aware of some specific Python syntax requirements and some datatype differences that will result in a slightly altered formatting of your statements for some datatypes. In this recipe, you'll learn how to construct valid query syntax and understand the nuances of how different datatypes alter the syntax as well as some Python-specific constructs. How to do it… Initially, we're going to take a look at how queries are constructed in ArcMap, so that you can get a feel of how they are structured. In ArcMap, open C:ArcpyBookCh8Crime_Ch8.mxd. Right-click on the Burglaries in 2009 layer and select Open Attribute Table. You should see an attribute table similar to the following screenshot. We're going to be querying the SVCAREA field: With the attribute table open, select the Table Options button and then Select by Attributes to display a dialog box that will allow you to construct an attribute query. Notice the Select * FROM Burglary WHERE: statement on the query dialog box (shown in the following screenshot). This is a basic SQL statement that will return all the columns from the attribute table for Burglary that meet the condition that we define through the query builder. The asterisk (*) simply indicates that all fields will be returned: Make sure that Create a new selection is the selected item in the Method dropdown list. This will create a new selection set. Double-click on SVCAREA from the list of fields to add the field to the SQL statement builder, as follows: Click on the = button. Click on the Get Unique Values button. From the list of values generated, double-click on 'North' to complete the SQL statement, as shown in the following screenshot: Click on the Apply button to execute the query. This should select 7520 records. Many people mistakenly assume that you can simply take a query that has been generated in this fashion and paste it into a Python script. That is not the case. There are some important differences that we'll cover next. Close the Select by Attributes window and the Burglaries in 2009 table. Clear the selected feature set by clicking on Selection | Clear Selected Features. Open the Python window and add the code to import arcpy. import arcpy Create a new variable to hold the query and add the exact same statement that you created earlier: qry = "SVCAREA" = 'North' Press Enter on your keyboard and you should see an error message similar to the following: Runtime error SyntaxError: can't assign to literal (<string>, line1) Python interprets SVCAREA and North as strings but the equal to sign between the two is not part of the string used to set the qry variable. There are several things we need to do to generate a syntactically correct statement for the Python interpreter. One important thing has already been taken care of though. Each field name used in a query needs to be surrounded by double quotes. In this case, SVCAREA is the only field used in the query and it has already been enclosed by double quotes. This will always be the case when you're working with shapefiles, file geodatabases, or ArcSDE geodatabases. Here is where it gets a little confusing though. If you're working with data from a personal geodatabase, the field names will need to be enclosed by square brackets instead of double quotes as shown in the following code example. This can certainly leads to confusion for script developers. qry = [SVCAREA] = 'North' Now, we need to deal with the single quotes surrounding 'North'. When querying data from fields that have a text datatype, the string being evaluated must be enclosed by quotes. If you examine the original query, you'll notice that we have in fact already enclosed the word North with quotes, so everything should be fine right? Unfortunately, it's not that simple with Python. Quotes, along with a number of other characters, must be escaped with a forward slash followed by the character being escaped. In this case, the escape sequence would be '. Alter your query syntax to incorporate the escape sequence: qry = "SVCAREA" = 'North' Finally, the entire query statement should be enclosed with quotes: qry = '"SVCAREA" = 'North'' In addition to the = sign, which tests for equality, there are a number of additional operators that you can use with strings and numeric data, including not equal (> <), greater than (<), greater than or equal to (<=), less than (>), and less than or equal to (>=). Wildcard characters including % and _ can also be used for shapefiles, file geodatabases, and ArcSDE geodatabases. These include % for representing any number of characters. The LIKE operator is often used with wildcard characters to perform partial string matching. For example, the following query would find all records with a service area that begins with N and has any number of characters after. qry = '"SVCAREA" LIKE 'N%'' The underscore character (_) can be used to represent a single character. For personal geodatabases the asterisk (*) is used to represent a wildcard character for any number of characters, while (?) represents a single character. You can also query for the absence of data, also known as NULL values. A NULL value is often mistaken for a value of zero, but that is not the case. NULL values indicate the absence of data, which is different from a value of zero. Null operators include IS NULL and IS NOT NULL. The following code example will find all records where the SVCAREA field contains no data: qry = '"SVCAREA" IS NULL' The final topic that we'll cover in this section are operators used for combining expressions where multiple query conditions need to be met. The AND operator requires that both query conditions be met for the query result to be true, resulting in selected records. The OR operator requires that at least one of the conditions be met. How it works… The creation of syntactically correct queries is one of the most challenging aspects of programming ArcGIS with Python. However, once you understand some basic rules, it gets a little easier. In this section, we'll summarize these rules. One of the more important things to keep in mind is that field names must be enclosed with double quotes for all datasets, with the exception of personal geodatabases, which require braces surrounding field names. There is also an AddFieldDelimiters() function that you can use to add the correct delimiter to a field based on the datasource supplied as a parameter to the function. The syntax for this function is as follows: AddFieldDelimiters(dataSource,field) Additionally, most people, especially those new to programming with Python, struggle with the issue of adding single quotes to string values being evaluated by the query. In Python, quotes have to be escaped with a single forward slash followed by the quote. Using this escape sequence will ensure that Python does in fact see that as a quote rather than the end of the string. Finally, take some time to familiarize yourself with the wildcard characters. For datasets other than personal geodatabases, you'll use the (%) character for multiple characters and an underscore (_) character for a single character. If you're using a personal geodatabase, the (*) character is used to match multiple characters and the (?) character is used to match a single character. Obviously, the syntax differences between personal geodatabases and all other types of datasets can lead to some confusion. Creating feature layers and table views Feature layers and table views serve as intermediate datasets held in memory for use specifically with tools such as Select by Location and Select Attributes. Although these temporary datasets can be saved, they are not needed in most cases. Getting ready Feature classes are physical representations of geographic data and are stored as files (shapefiles, personal geodatabases, and file geodatabases) or within a geodatabase. ESRI defines a feature class as "a collection of features that shares a common geometry (point, line, or polygon), attribute table, and spatial reference." Feature classes can contain default and user-defined fields. Default fields include the SHAPE and OBJECTID fields. These fields are maintained and updated automatically by ArcGIS. The SHAPE field holds the geometric representation of a geographic feature, while the OBJECTID field holds a unique identifier for each feature. Additional default fields will also exist depending on the type of feature class. A line feature class will have a SHAPE_LENGTH field. A polygon feature class will have both, a SHAPE_LENGTH and a SHAPE_AREA field. Optional fields are created by end users of ArcGIS and are not automatically updated by GIS. These contain attribute information about the features. These fields can also be updated by your scripts. Tables are physically represented as standalone DBF tables or within a geodatabase. Both, tables and feature classes, contain attribute information. However, a table contains only attribute information. There isn't a SHAPE field associated with a table, and they may or may not contain an OBJECTID field. Standalone Python scripts that use the Select by Attributes or Select by Location tool require that you create an intermediate dataset rather than using feature classes or tables. These intermediate datasets are temporary in nature and are called Feature Layers or Table Views. Unlike feature classes and tables, these temporary datasets do not represent actual files on disk or within a geodatabase. Instead, they are "in memory" representations of feature classes and tables. These datasets are active only while a Python script is running. They are removed from memory after the tool has executed. However, if the script is run from within ArcGIS as a script tool, then the temporary layer can be saved either by right-clicking on the layer in the table of contents and selecting Save As Layer File or simply by saving the map document file. Feature layers and table views must be created as a separate step in your Python scripts, before you can call the Select by Attributes or Select by Location tools. The Make Feature Layer tool generates the "in-memory" representation of a feature class, which can then be used to create queries and selection sets, as well as to join tables. After this step has been completed, you can use the Select by Attributes or Select by Location tool. Similarly, the Make Table View tool is used to create an "in-memory" representation of a table. The function of this tool is the same as Make Feature Layer. Both the Make Feature Layer and Make Table View tools require an input dataset, an output layer name, and an optional query expression, which can be used to limit the features or rows that are a part of the output layer. In addition, both tools can be found in the Data Management Tools toolbox. The syntax for using the Make Feature Layer tool is as follows: arcpy.MakeFeatureLayer_management(<input feature layer>, <output layer name>,{where clause}) The syntax for using the Make Table View tool is as follows: Arcpy.MakeTableView_management(<input table>, <output table name>, {where clause}) In this recipe, you will learn how to use the Make Feature Layer and Make Table View tools. These tasks will be done inside ArcGIS, so that you can see the in-memory copy of the layer that is created. How to do it… Follow these steps to learn how to use the Make Feature Layer and Make Table View tools: Open c:ArcpyBookCh8Crime_Ch8.mxd in ArcMap. Open the Python window. Import the arcpy module: import arcpy Set the workspace: arcpy.env.workspace = "c:/ArcpyBook/data/CityOfSanAntonio.gdb" Start a try block: try: Make an in-memory copy of the Burglary feature class using the Make Feature Layer tool. Make sure you indent this line of code: flayer = arcpy.MakeFeatureLayer_management("Burglary","Burglary_ Layer") Add an except block and a line of code to print an error message in the event of a problem: except: print "An error occurred during creation" The entire script should appear as follows: import arcpy arcpy.env.workspace = "c:/ArcpyBook/data/CityOfSanAntonio.gdb" try: flayer = arcpy.MakeFeatureLayer_management("Burglary","Burglary_ Layer") except: print "An error occurred during creation" Save the script to c:ArcpyBookCh8CreateFeatureLayer.py. Run the script. The new Burglary_Layer file will be added to the ArcMap table of contents: The Make Table View tool functionality is equivalent to the Make Feature Layer tool. The difference is that it works against standalone tables instead of feature classes. Remove the following line of code: flayer = arcpy.MakeFeatureLayer_management("Burglary","Burglary_ Layer") Add the following line of code in its place: tView = arcpy.MakeTableView_management("Crime2009Table", "Crime2009TView") Run the script to see the table view added to the ArcMap table of contents. How it works... The Make Feature Layer and Make Table View tools create in-memory representations of feature classes and tables respectively. Both the Select by Attributes and Select by Location tools require that these temporary, in-memory structures be passed in as parameters when called from a Python script. Both tools also require that you pass in a name for the temporary structures. There's more... You can also apply a query to either the Make Feature Layer or Make Table View tools to restrict the records returned in the feature layer or table view. This is done through the addition of a where clause when calling either of the tools from your script. This query is much the same as if you'd set a definition query on the layer through Layer Properties | Definition Query. The syntax for adding a query is as follows: MakeFeatureLayer(in_features, out_layer, where_clause) MakeTableView(in_table, out_view, where_clause)
Read more
  • 0
  • 0
  • 9198
article-image-core-http-module-nginx
Packt
08 Jul 2011
8 min read
Save for later

The Core HTTP Module in Nginx

Packt
08 Jul 2011
8 min read
Nginx 1 Web Server Implementation Cookbook Over 100 recipes to master using the Nginx HTTP server and reverse proxy   Setting up the number of worker processes correctly Nginx like any other UNIX-based server software, works by spawning multiple processes and allows the configuration of various parameters around them as well. One of the basic configurations is the number of worker processes spawned! It is by far one of the first things that one has to configure in Nginx. How to do it... This particular configuration can be found at the top of the sample configuration file nginx.conf: user www www; worker_processes 5; error_log logs/error.log; pid logs/nginx.pid; worker_rlimit_nofile 8192; events { worker_connections 4096; } In the preceding configuration, we can see how the various process configurations work. You first set the UNIX user under which the process runs, then you can set the number of worker processes that Nginx needs to spawn, after that we have some file locations where the errors are logged and the PIDs (process IDs) are saved. How it works... By default, worker_processes is set at 2. It is a crucial setting in a high performance environment as Nginx uses it for the following reasons: It uses SMP, which allows you to efficiently use multi-cores or multi-processors systems very efficiently and have a definite performance gain. It increases the number of processes decreases latency as workers get blocked on disk I/O. It limits the number of connections per process when any of the various supported event types are used. A worker process cannot have more connections than specified by the worker_connections directive. There's more... It is recommended that you set worker_processes as the number of cores available on your server. If you know the values of worker_processes and worker_connections, one can easily calculate the maximum number of connections that Nginx can handle in the current setup. Maximum clients = worker_processes * worker_connections   Increasing the size of uploaded files Usually when you are running a site where the user uploads a lot of files, you will see that when they upload a file which is more than 1MB in size you get an Nginx error stating, "Request entity too Large" (413), as shown in the following screenshot. We will look at how Nginx can be configured to handle larger uploads. How to do it... This is controlled by one simple part of the Nginx configuration. You can simply paste this in the server part of the Nginx configuration: client_max_body_size 100M; # M stands for megabytes This preceding configuration will allow you to upload a 100 megabyte file. Anything more than that, and you will receive a 413. You can set this to any value which is less than the available disk space to Nginx, which is primarily because Nginx downloads the file to a temporary location before forwarding it to the backend application. There's more... Nginx also lets us control other factors related to people uploading files on the web application, like timeouts in case the client has a slow connection. A slow client can keep one of your application threads busy and thus potentially slow down your application. This is a problem that is experienced on all the heavy multimedia user-driven sites, where the consumer uploads all kinds of rich data such as images, documents, videos, and so on. So it is sensible to set low timeouts. client_body_timeout 60; # parameter in seconds client_body_buffer_size 8k; client_header_timeout 60; # parameter in seconds client_header_buffer_size 1k; So, here the first two settings help you control the timeout when the body is not received at one read-step (basically, if the server is queried and no response comes back). Similarly, you can set the timeout for the HTTP header as well. The following table lists out the various directives and limits you can set around client uploading.   Using dynamic SSI for simple sites With the advent of modern feature-full web servers, most of them have Server-Side Includes (SSI) built in. Nginx provides easy SSI support which can let you do pretty much all basic web stuff. How to do it... Let's take a simple example and start understanding what one can achieve with it. Add the following code to the nginx.conf file: server { ..... location / { ssi on; root /var/www/www.example1.com; } } Add the following code to the index.html file: <html> <body> <!--# block name="header_default" --> the header testing <!--# endblock --> <!--# include file="header.html" stub="header_default" --> <!--# echo var="name" default="no" --> <!--# include file="footer.html"--> </body> </html> Add the following code to the header.html file: <h2>Simple header</h2> Add the following code to the footer.html file: <h2>Simple footer</h2> How it works... This is a simple example where we can see that you can simply include some partials in the larger page, and in addition to that you can create block as well within the page. So the <block> directive allows you to create silent blocks that can be included later, while the <include> directive can be used to include HTML partials from other files, or even URL end points. The <echo> directive is used to output certain variables from within the Nginx context. There's more... You can utilize this feature for all kinds of interesting setups where: You are serving different blocks of HTML for different browsers types You want to optimize and speed up certain common blocks of the sites You want to build a simple site with template inheritance without installing any other scripting language   Adding content before and after a particular page Today, in most of the sites that we visit, the webpage structure is formally divided into a set of boxes. Usually, all sites have a static header and a footer block. Here, in this following page you can see the YUI builder generating the basic framework of such a page. In such a scenario, Nginx has a really useful way of adding content before and after it serves a certain page. This will potentially allow you to separate the various blocks and optimize their performance individually, as well. Let's have a look at an example page: So here we want to insert the header block before the content, and then append the footer block: How to do it… The sample configuration for this particular page would look like this: server { listen 80; server_name www.example1.com; location / { add_before_body /red_block add_after_body /blue_block; ... } location /red_block/ { ... } location /blue_block/ { .... } } This can act as a performance enhancer by allowing you to load CSS based upon the browser only. There can be cases where you want to introduce something into the header or the footer on short notice, without modifying your backend application. This provides an easy fix for those situations. This module is not installed by default and it is necessary to enable it when building Nginx. ./configure –with-http_addition_module   Enabling auto indexing of a directory Nginx has an inbuilt auto-indexing module. Any request where the index file is not found will route to this module. This is similar to the directory listing that Apache displays. How to do it... Here is the example of one such Nginx directory listing. It is pretty useful when you want to share some files over your local network. To start auto index on any directory all you need to do is to carry out the following example and place it in the server section of the Nginx configuration file: server { location 80; server_name www.example1.com; location / { root /var/www/test; autoindex on; } } How it works... This will simply enable auto indexing when the user types in http://www.example1.com. You can also control some other things in the listings in this way: autoindex_exact_size off; This will turn off the exact file size listing and will only show the estimated sizes. This can be useful when you are worried about file privacy issues. autoindex_localtime on; This will represent the timestamps on the files as your local server time (it is GMT by default): This image displays a sample index auto-generated by Nginx using the preceding configuration. You can see the filenames, timestamp, and the file sizes as the three data columns.  
Read more
  • 0
  • 0
  • 9198

article-image-network-access-control-lists
Packt
27 Nov 2014
6 min read
Save for later

Network Access Control Lists

Packt
27 Nov 2014
6 min read
In this article by Ryan Boud, author of Hyper-V Network Virtualization Cookbook, we will learn to lock down a VM for security access. (For more resources related to this topic, see here.) Locking down a VM for security access This article will show you how to apply ACLs to VMs to protect them from unauthorized access. Getting ready You will need to start two VMs in the Tenant A VM Network: in this case, Tenant A – VM 10, to test the gateway and as such should have IIS installed) and Tenant A – VM 11. How to do it... Perform the following steps to lock down a VM: In the VMM console, click on the Home tab in the ribbon bar and click on the PowerShell button. This will launch PowerShell with the VMM module already loaded and the console connected to the current VMM instance. To obtain the Virtual Subnet IDs for all subnets in the Tenant A VM Network, enter the following PowerShell: $VMNetworkName = "Tenant A" $VMNetwork = Get-SCVMNetwork | Where-Object -Property Name -EQ $VMNetworkName Get-SCVMSubnet -VMNetwork $VMNetwork | Select-Object VMNetwork,Name,SubnetVlans,VMSubnetID You will be presented with the list of subnets and the VMSubnetID for each. The VMSubnetID will used later in this article; in this case, the VMSubnetID is 4490741, as shown in the following screenshot: Your VMSubnet ID value may be different to the one obtained here; this is normal behavior. In the PowerShell Console, run the following PowerShell to get the IP addresses of Tenant A – VM 10 and Tenant A – VM 11: $VMs = @() $VMs += Get-SCVirtualMachine -Name "Tenant A - VM 10" $VMs += Get-SCVirtualMachine -Name "Tenant A - VM 11" ForEach($VM in $VMs){    Write-Output "$($VM.Name): $($VM.VirtualNetworkAdapters.IPv4Addresses)"    Write-Output "Host name: $($VM.HostName)" } You will be presented with the IPv4 addresses for the two VMs as shown in the following screenshot: Please leave this PowerShell console open. Your IP addresses and host names may differ from those shown here; this is normal behavior. In the VMM console, open the VMs and Services workspace and navigate to All Hosts | Hosts | hypvclus01. Right-click on Tenant A – VM 11, navigate to Connect or View, and then click on Connect via Console. Log in to the VM via the Remote Console. Open Internet Explorer and go to the URL http://10.0.0.14, where 10.0.0.14 is the IP address of Tenant A – VM 10, as we discussed in step 4. You will be greeted with default IIS page. This shows that there are currently no ACLs preventing Tenant A – VM 11 accessing Tenant A – VM 10 within Hyper-V or within the Windows Firewall. Open a PowerShell console on Tenant A – VM 11 and enter the following command: Ping 10.0.0.14 –t Here, 10.0.0.14 is the IP address of Tenant A – VM 10. This will run a continuous ping against Tenant A – VM10. In the PowerShell console left open in Step 4, enter the following PowerShell: Invoke-Command -ComputerName HYPVCH1.ad.demo.com - ScriptBlock{    Add-VMNetworkAdapterExtendedAcl -Action Deny -Direction      Inbound -VMName "Tenant A - VM 10" -Weight 1 -        IsolationID 4490741 } Here, HYPVCH1.ad.demo.com is the name of the host where Tenant A – VM 10 is running, as obtained in step 4 and the Isolation ID needs to be VMSubnetID as obtained in step 2. Please leave this PowerShell console open. When adding base rules such as a Deny All, it is suggested to apply a weight of 1 to allow other rules to override it if appropriate. Return to the PowerShell console left open on Tenant A – VM 11 in step 10. You will see that Tenant A – VM 10 has stopped responding to pings. This has created a Hyper-V Port ACL that will deny all inbound traffic to Tenant A – VM10. In the same PowerShell console, enter the following PowerShell: Test-NetConnection -CommonTCPPort HTTP -ComputerName 10.0.0.14 -InformationLevel Detailed Here, 10.0.0.14 is the IP address of Tenant A – VM 10. This shows that you cannot access the IIS website on Tenant A – VM 10. Return to the PowerShell console left open on the VMM console in step 11 and enter the following PowerShell cmdlets: Invoke-Command -ComputerName HYPVCH1.ad.demo.com - ScriptBlock{    Add-VMNetworkAdapterExtendedAcl -Action Allow -      Direction Inbound -VMName "Tenant A - VM 10" -Weight        10 -IsolationID 4490741 -LocalPort 80 } Here, HYPVCH1.ad.demo.com is the name of the host where Tenant A – VM 10 is running, as obtained in step 4, and the Isolation ID needs to be set to VMSubnetID as obtained in step 2. Please leave this PowerShell console open. When adding rules it is suggested to use weight increments of 10 to allow other rules to be inserted between rules if necessary. On Tenant A – VM 11, repeat step 13. You will see that TCPTestSucceeded has changed to True. Return to the PowerShell console left open on the VMM console in step 14, and enter the following PowerShell cmdlets: Invoke-Command -ComputerName HYPVCH1.ad.demo.com - ScriptBlock{    Add-VMNetworkAdapterExtendedAcl -Action Deny -Direction      Outbound -VMName "Tenant A - VM 10" -Weight 1 -        IsolationID 4490741 } Here, HYPVCH1.ad.demo.com is the name of the host where Tenant A – VM 10 is running, as obtained in step 4, and the Isolation ID needs to be set to VMSubnetID as obtained in step 2. Please leave this PowerShell console open. When adding base rules such as a Deny All, it is suggested to apply a weight of 1 to allow other rules to override it if appropriate. On Tenant A – VM 11 repeat step 14. You will see that TCPTestSucceeded has changed to False. This is because all outbound connections have been denied. Return to the PowerShell console left open on the VMM console in step 17, and enter the following PowerShell cmdlets: Invoke-Command -ComputerName HYPVCH1.ad.demo.com - ScriptBlock{    Remove-VMNetworkAdapterExtendedAcl -Direction Inbound -      VMName "Tenant A - VM 10" -Weight 10 } This removes the inbound rule for port 80. In the same PowerShell console enter the following cmdlets: Invoke-Command -ComputerName HYPVCH1.ad.demo.com - ScriptBlock{    Add-VMNetworkAdapterExtendedAcl -Action Allow -      Direction Inbound -VMName "Tenant A - VM 10" -Weight        10 -IsolationID 4490741 -LocalPort 80 -Stateful          $True -Protocol TCP } This adds a stateful ACL rule; this ensures that the switch dynamically creates an outbound rule to allow the traffic to return to the requestor. On Tenant A – VM 11 repeat step 14. You will see that the TCPTestSucceeded has changed to True. This is because the stateful ACL is now in place. How it works... Extended ACLs are applied as traffic ingresses and egresses the VM into and out of the Hyper-V switch. As the ACLs are VM-specific, they are stored in the VM's configuration file. This ensures that the ACLs are moved with the VM ensuring continuity of ACL. For the complete range of options, it is advisable to review the TechNet article at http://technet.microsoft.com/en-us/library/dn464289.aspx. Summary In this article we learned how to lock down a VM for security access. Resources for Article: Further resources on this subject: High Availability Scenarios [Article] Performance Testing and Load Balancing [Article] Your first step towards Hyper-V Replica [Article]
Read more
  • 0
  • 0
  • 9195

article-image-how-to-stream-live-video-with-raspberry-pi
Jakub Mandula
07 Dec 2015
5 min read
Save for later

How to Stream Live Video With Raspberry Pi

Jakub Mandula
07 Dec 2015
5 min read
Say you want to build a remote controlled robot or a surveillance camera using your Raspberry Pi. What is the best method of transmitting the live footage to your screen? If only there was a program that could do this in a simple way while not frying your Pi. Fortunately, there is a program called mjpg-streamer to save the day. In its core, it grabs images from one input device and forwards them to one or more output devices. We are going to provide it with the video from our web-camera and feed it into a self-hosted HTTP server that lets us display the images in the browser. Dependencies Let's get started! mjpg-streamer does not come as a standard package and must be compiled manually. But do not let that be the reason for giving up on it. In order to compile mjpg-streamer, we have to install several dependencies. sudo apt-get update sudo apt-get upgrade sudo apt-get install build-essential libjpeg8-dev imagemagick libv4l-dev Recently the videodev.h file has been replaced by a newer version videodev2.h. In order to fix the path references, just create a quick symbolic link. sudo ln -s /usr/include/linux/videodev2.h /usr/include/linux/videodev.h Downloading Now that we have all the dependencies we can download the mjpg-streamer repository. I am using a Github fork by jacksonliam. git clone git@github.com:jacksonliam/mjpg-streamer.git cd mjpg-streamer/mjpg-streamer-experimental Compilation There is a number of plugins that come with MJPEG-streamer. We are going to only compile these: input_file.so - used to provide a file as input input_uvc.so - provides input form USB web cameras input_raspicam.so - provides input from the raspicam module output_http.so - our http streaming output Feel free to look through the rest of the plugins folder and explore the other inputs/outputs. Just add their names to the command below. make mjpg_streamer input_file.so input_uvc.so input_raspicam.so output_http.so Moving mjpg-streamer I recommend moving mjpg-streamer to a more permanent location in your file system. I personally use the /usr/local directory. But feel free to use any other path as long as you adjust any following steps in the setup process. sudo cp mjpg_streamer /usr/local/bin sudo cp input_file.so input_uvc.so input_raspicam.so output_http.so /usr/local/lib/ sudo cp -R www /usr/local/www Finally reference the plugins in your bashrc file. Simply open it with your favorite text editor. vim ~/.bashrc And append the following line to the file: export LD_LIBRARY_PATH=/usr/local/lib/ You can a Now source your bash and you are good to go. source ~/.bashrc Running mjpg-streamer Running mjpg-streamer is very simple. If you have followed all the steps up to now all you have to do is one command. mjpg_streamer -i input_uvc.so -o "output_http.so -w /usr/local/www" The flags mean the following: * -i - input to mjpg-streamer (our USB camera) * -o output from mjpg-streamer (our HTTP server) * -w a flag to the HTTP server of the location with the HTML and CSS which we moved to /usr/local/www. There is a vast number of other flags that you can explore. Here I list a few of them. -f - framerate in seconds -c - protect the HTTP server with a username:password -b - run in background -p - use another port Testing the stream Now that you have your mjpg-streamer running go to http://ip-of-your-raspberry-pi:8080 and watch the live stream. To just grab the stream, paste the following image tag into your HTML <img src="http://ip-of-your-raspberry-pi:8080/?action=stream"> This should work in most modern browsers. I found there to be a problem with Google Chrome on iOS devices, which is strange because it does work in Safari which is basically identical to Chrome. Securing the stream You could leave it at that. However as of now your stream is insecure and anyone with the IP address to your Raspberry Pi can access it. We have talked about the -c flag which can be passed to the output_http.so plugin. However, this does not prevent people eavesdropping on your connection. We need to use HTTPS. The easiest way to secure your mjpg-stream is using a utility called stunnel. Stunnel is a very lightweight HTTPS-proxy. You give it all the keys and certificates and a two ports. stunnel then forwards the traffic from one port to the other while silently encrypting it. The installation is very simple. sudo apt-get install stunnel4 Next you have to generate an RSA key and certificate. This is very easy with OpenSSL openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 720 -nodes Just fill the prompts with your information. This creates a 2048-bit RSA key pair and a self-signed certificate valid for 720 days. Now create the following configuration file stunnel.conf. ; Paths to your key and certificate you generated in the previous step key=./key.pem cert=./cert.pem debug=7 [https] clinet=no accept=1234 ; Secure port connect=8080 ; mjpg streamer port sslVersion=all Now the last thing to do is start stunnel. sudo stunnel4 stunnel.conf Go to https://ip-of-your-raspberry-pi:1234. Confirm that you trust this certificate (it is self-signed so most browsers will complain about the security). Conclusion Now you can enjoy a live and secure stream directly from your Raspberry Pi. You can integrate it in your Home security system or on a robot. You can also grab the stream and use OpenCV to implement some cool computer vision ability. I used this on my PiNet Project to build a robot that can be controlled over the internet using a Webcam. I am curious what you can come up with! About the author Jakub Mandula is a student interested in anything to do with technology, computers, mathematics or science.
Read more
  • 0
  • 0
  • 9190
article-image-networking-tcl-using-udp-sockets
Packt
29 Jun 2010
10 min read
Save for later

Networking in Tcl: Using UDP Sockets

Packt
29 Jun 2010
10 min read
(For more resources on Tcl, see here.) TCP support is built in to the core of the Tcl interpreter. To be able to use the UDP protocol, you have to use an external package. The default choice is usually the TclUDP extension, which is available from http://sourceforge.net/projects/tcludp/ (it also comes as a part of ActiveTcl bundle; if you don't have it, install it with teacup install udp). In contrast to TCP, which is a connection-oriented protocol, UDP is connection-less. This means that every data package (datagram) travels from one peer to another on its own, without a return acknowledgement or retransmission in the case of lost packets. What is more, one of the peers may send packages that are never received (for example if the second peer is not listening at the moment), and there is no feedback information that something is going wrong. This implies a difference in the design for handling the transmission, which will be illustrated in the following example. Creating a UDP-based client Lets consider a simple 'time server', where the server sends the current time to any client application that subscribes for such notifications, of course using UDP connectivity. The format of each datagram will be rather simple: it will contain only the current time expressed in seconds. First let's have a look on client code: package require udpset s [udp_open]fconfigure $s -buffering nonefconfigure $s -remote [list 127.0.0.1 9876]puts -nonewline $s "subscribe"proc readTime {channel} { puts "Time from server: [read $channel]"}fileevent $s readable [list readTime $s]vwait foreverclose $s As you have probably figured out, the first line loads the TclUDP extension. The next line creates a UDP socket, using the udp_open command, and stores its reference in the s variable. The UDP protocol uses ports in the same way as TCP. If we executed udp_open 1234, the port value 1234 would be specified, but if omitted, the operating system would assign a random port. Note that if you specify a port that is already being used by any other program, an error will be generated. Next, we set the buffering mode to none, meaning that the output buffer will be automatically flushed after every output operation. We will discuss buffering issues more deeply later in this example. The newly created UDP socket is not connected to anything, as the UDP is connection-less. Such a socket is able to receive packets as they arrive at any time from any source, without establishing a data connection of any type. To have datagrams be sent to a specific destination, you should use the fconfigure command with a new option (introduced by TclUDP) –remote, along with a two-item list containing the target address and port: fconfigure $s -remote [list 127.0.0.1 9876]. In this example the server will be executed on local host (so you are able to run it even if you are not part of a network). Note that you can call this command any time you wish, causing successive datagrams to be sent to different peers. Now it is time to send a message to the server – in this case simply a string containing 'subscribe'. If –nonewline is omitted, puts would generate 2 datagrams (the second one containing the newline character) – it is likely that the puts implementation will write data twice to the buffer (the message, and then the new line character), and as the buffering is set to none, it is flushed immediately after each write. The other solution would be to set buffering to full and call flush $s after each socket write. The handling of incoming data is implemented based on event programming. The line: fileevent $s readable [list readTime $s] defines that every time the socket has some data to read (is readable), the command readTime with $s as an argument is called. The command itself is simple – it prints to the screen every piece of data that comes from the socket, read with the read $s command. Implementing service using UDP The code for the server is a bit more complicated, due to a need to track subscribed clients: package require udpset clients [list]proc registerClient {s} { global clients lappend clients [fconfigure $s -peer]}proc sendTime {s} { global clients foreach peer $clients { puts "sending to $peer" fconfigure $s -remote $peer puts -nonewline $s [clock seconds] } after 1000 [list sendTime $s]}set server [udp_open 9876]fconfigure $server -buffering nonefileevent $server readable [list registerClient $server]sendTime $servervwait forever The list named clients will hold an entry for each subscribed client; each entry is also a list containing IP address and port, so it suits perfectly for the fconfigure $s –remote command. The server opens a UDP socket on port 9876. We would like to avoid the word 'listens' in this context, as this socket does not differ in any way from the one used by the client. By contrast, TCP requires a special server type socket, for listening purposes. On every incoming data even, the registerClient procedure is executed. The command appends to the client's list information about the originator of the data (usually referred to as a peer) that has just arrived. This information is retrieved with fconfigure $s –peer. Although it may seem that this data is defined for the socket (represented by $s), in reality it refers to the most recent datagram received by this socket.   Every one second the procedure sendTime is called. The purpose of this command is to send the current time to all subscribed clients, so it iterates over the clients list, and for each one it first configures the socket with the target address and port (fconfigure $s -remote $peer), and then sends a datagram containing the time in the form of the output from the clock seconds command.   The server code is simple, it runs forever and there is no way to unsubscribe from receiving the data, but it demonstrates how to work with UDP in Tcl. The following picture shows an example of the execution of the server (timeServer.tcl)and two clients (timeClient.tcl): The first client connects from the port 4508, and the second one (started a few seconds later) from 4509. The most important observation is that UDP sockets are handled identically on both the client and server, so the name 'server' is actually contractual. It is worth mentioning that TclUDP supports multicasting and broadcasting of UDP packets. For details of how to perform this, please consult the package's manual. Sending reliable messages The UDP protocol lacks reliability, which is one of its main differences compared to TCP. Applications using UDP must either accept the fact that some of the datagrams may be lost, or implement equivalent functionality on their own. The same is true of topics like the order of incoming packets and data integrity. The implementation of such logic could be as follows in the following example that follows — the sender calculates the MD5 checksum of the data, and sends both to the receiver. The receiver calculates the checksum again and compares it to the received one – and in the case of equality, sends acknowledgment (in this example, the checksum is sent back). The sender will repeatedly attempt to send the data until the confirmation is received, or the permitted number of attempts has been reached. The sender code is as follows: package require udppackage require md5set s [udp_open]fconfigure $s -buffering nonefconfigure $s -remote [list 127.0.0.1 9876]proc randomData {length} { set result "" for {set x 0} {$x<$length} {incr x} { set result "$result[expr { int(2 * rand()) }]" } return $result}proc sendPacket {chan contents {retryCount 3}} { variable ackArray if {$retryCount < 1} { puts "packet delivery failure" return } set md5 [md5::md5 -hex $contents] # if ack received, remove ack and do not send again if {[info exists ackArray($md5)]} { puts "packet successfully delivered" unset ackArray($md5) return } puts "sending packet, # of retries: $retryCount" puts "packet content: $md5$contents" puts -nonewline $chan "$md5$contents" flush $chan # handle retries incr retryCount -1 after 1000 sendPacket [list $chan $contents $retryCount]}proc recvAckPacket {chan} { variable ackArray set md5 [read $chan] puts "received ack: $md5" set ackArray($md5) 1 }sendPacket $s [randomData 48]after 5000 sendPacket $s [randomData 48]after 10000 sendPacket $s [randomData 48]fileevent $s readable [list recvAckPacket $s]vwait forever The main logic is located in the sendPacket procedure. The last parameter is the number of retries left to deliver the data. The procedure calculates the MD5 checksum of the data to be sent (stored in contents variable) and first checks if the appropriate acknowledgment has already been received – if the array ackArray contains the entry for the checksum (that is concurrently an acknowledgment), it is removed and the datagram is considered to have been delivered. If it is not, then the checksum along with the data is sent to the receiver, and a sendPacket is scheduled to be executed again after one second, every time with retries counter decreased. If the procedure is called when the counter is equal to zero, the delivery is considered to be negative. The acknowledgments are received by the procedure recvAckPacket, which simply stores it into ackArray, allowing sendPacket to find it and react appropriately. The helper procedure randomData allows the generation of a random string of zeroes and ones of a given length. Note that this example does not cover the topic of received packets order. The receiver code: package require udppackage require md5 set server [udp_open 9876]fconfigure $server -buffering nonefileevent $server readable [list recvPacket $server]proc recvPacket {chan} { variable readPackets set data [read $chan] puts "received: $data" set md5 [string range $data 0 31] set contents [string range $data 32 end] if {$md5 != [md5::md5 -hex $contents]} { #the data are malformed puts "malformed data" return } # send an ack anyway, because original # might not have been received by other peer fconfigure $chan -remote [fconfigure $chan -peer] #simulate the ack package lost over network if {10*rand() > 7} { puts -nonewline $chan $md5 flush $chan } # check if this packet is not a duplicate if {[info exists readPackets($md5)]} { return } set readPackets($md5) [clock seconds] # handle packet here...}proc periodicCleanup {} { variable readPackets set limit [clock scan "-300 seconds"] foreach {md5 clock} [array get readPackets] { if {$clock < $limit} { unset readPackets($md5) } } after 60000 periodicCleanup}vwait forever The receiver will send back the acknowledgement each time the correct datagram is received, that is when the checksums sent (first 32 chars) and calculated locally are equal. It also stores in the readPackets array the time of arrival of each packet, which allows us to detect duplicated data and processing it only once. To make the example more vivid, about 70% of data loss is simulated by randomly not sending confirmations. The receiver also implements some simple logic for periodic clean up of the received datagrams log, to prevent it from becoming too huge and memory consumptive. The result of running the example can be as depicted: In this example, the first datagram was delivered successfully on the first attempt, the second one's delivery failed despite 3 attempts, and the last one was delivered on the second try. Summary In this article we saw how to handle the UDP communication in Tcl, with TclUDP extension as the implementation. Further resources on this subject: Tcl: Handling Email [article] Extending Applications in Tcl [article] Managing Certificates from Tcl [article]
Read more
  • 0
  • 0
  • 9185

article-image-apache-wicket-displaying-data-using-datatable
Packt
01 Apr 2011
6 min read
Save for later

Apache Wicket: displaying data using DataTable

Packt
01 Apr 2011
6 min read
It's hard to find a web application that does not have a single table that presents the user with some data. Building these DataTables, although not very difficult, can be a daunting task because each of these tables must often support paging, sorting, filtering, and so on. Wicket ships with a very powerful component called the DataTable that makes implementing all these features simple and elegant. Because Wicket is component-oriented, once implemented, these features can be easily reused across multiple DataTable deployments. In this article, we will see how to implement the features mentioned previously using the DataTable and the infrastructure it provides. Sorting A common requirement, when displaying tabular data, is to allow users to sort it by clicking the table headers. Click a header once and the data is sorted on that column in ascending order; click it again, and the data is sorted in the descending order. In this recipe, we will see how to implement such a behavior when displaying data using a DataTable component. We will build a simple table that will look much like a phone book and will allow the sorting of data on the name and e-mail columns: Getting ready Begin by creating a page that will list contacts using the DataTable, but without sorting: Create Contact bean: Contact.java public class Contact implements Serializable { public String name, email, phone; // getters, setters, constructors2. Create the page that will list the contacts: HomePage.html <html> <body> <table wicket_id="contacts" class="contacts"></table> </body> </html> HomePage.java public class HomePage extends WebPage { private static List<Contact> contacts = Arrays.asList( new Contact("Homer Simpson", "homer@fox.com", "555-1211"), new Contact("Charles Burns", "cmb@fox.com", "555-5322"), new Contact("Ned Flanders", "green@fox.com", "555-9732")); public HomePage(final PageParameters parameters) { // sample code adds a DataTable and a data providert hat uses the contacts list created above } } How to do it... Enable sorting by letting DataTable columns know they can be sorted by using a constructor that takes the sort data parameter: HomePage.java List<IColumn<Contact>> columns = new ArrayList<IColumn<Contact>>(); columns.add(new PropertyColumn<Contact>(Model.of("Name"), "name","name")); columns.add(new PropertyColumn<Contact>(Model.of("Email"), "email", "email")); columns.add(new PropertyColumn<Contact>(Model.of("Phone"), "phone")); Implement sorting by modifying the data provider: private static class ContactsProvider extends SortableDataProvider<Contact> { public ContactsProvider() { setSort("name", true); } public Iterator<? extends Contact> iterator(int first, int count) { List<Contact> data = new ArrayList<Contact>(contacts); Collections.sort(data, new Comparator<Contact>() { public int compare(Contact o1, Contact o2) { int dir = getSort().isAscending() ? 1 : -1; if ("name".equals(getSort().getProperty())) { return dir * (o1.name.compareTo(o2.name)); } else { return dir * (o1.email.compareTo(o2.email)); } } }); return data.subList(first, Math.min(first + count, data.size())).iterator(); } public int size() { return contacts.size(); } public IModel<Contact> model(Contact object) { return Model.of(object); } } How it works... DataTable supports sorting out of the box. Any column with the IColumn#getSortProperty() method that returns a non-null value is treated as a sortable column and Wicket makes its header clickable. When a header of a sortable column is clicked Wicket will pass the value of IColumn#getSortProperty to the data provider which should use this value to sort the data. In order to know about the sorting information the data provider must implement the ISortableDataProvider interface; Wicket provides the default SortableDataProvider implementation which is commonly used to implement sort-capable data providers. DataTable will take care of details such as multiple clicks to the same column resulting in change of sorting direction, so on. Let's examine how to implement sorting in practice. In step 1 and 2, we have implemented a basic DataTable that cannot yet sort data. Even though the data provider we have implemented already extends a SortableDataProvider, it does not yet take advantage of any sort information that may be passed to it. We start building support for sorting by enabling it on the columns, in our case the name and the email columns: List<IColumn<Contact>> columns = new ArrayList<IColumn<Contact>>(); columns.add(new PropertyColumn<Contact>(Model.of("Name"), "name", "name")); columns.add(new PropertyColumn<Contact>(Model.of("Email"), "email", "email")); columns.add(new PropertyColumn<Contact>(Model.of("Phone"), "phone")); We enable sorting on the columns by using the three-argument constructor of the PropertyColumn, with the second argument being the "sort data". Whenever a DataTable column with sorting enabled is clicked, the data provider will be given the value of the "sort data". In the example, only the name and e-mail columns have sorting enabled with the sort data defined as a string with values "name" and "e-mail" respectively. Now, let's implement sorting by making our data provider implementation sort-aware. Since our data provider already extends a provider that implements ISortableDataProvider we only need to take advantage of the sort information: public Iterator<? extends Contact> iterator(int first, int count) { List<Contact> data = new ArrayList<Contact>(contacts); Collections.sort(data, new Comparator<Contact>() { public int compare(Contact o1, Contact o2) { int dir = getSort().isAscending() ? 1 : -1; if ("name".equals(getSort().getProperty())) { return dir * (o1.name.compareTo(o2.name)); } else { return dir * (o1.email.compareTo(o2.email)); } } }); return data.subList(first, Math.min(first + count, data.size())).iterator(); } First we copy the data into a new list which we can sort as needed and then we sort based on the sort data and direction provided. The value returned by getSort().getProperty() is the same sort data values we have defined previously when creating columns. The only remaining task is to define a default sort which will be used when the table is rendered before the user clicks any header of a sortable column. We do this in the constructor of our data provider: public ContactsProvider() { setSort("name", true); } There's more... DataTable gives us a lot out of the box; in this section we see how to add some usability enhancements. Adding sort direction indicators via CSS DataTable is nice enough to decorate sortable <th> elements with sort-related CSS classes out of the box. This makes it trivial to implement sort direction indicators as shown in the following screenshot: A possible CSS style definition can look like this: table tr th { background-position: right; background-repeat:no-repeat; } table tr th.wicket_orderDown { background-image: url(images/arrow_down.png); } table tr th.wicket_orderUp { background-image: url(images/arrow_up.png); } table tr th.wicket_orderNone { background-image: url(images/arrow_off.png);
Read more
  • 0
  • 1
  • 9181
Modal Close icon
Modal Close icon