Oracle: semget failed!

I had an issue with starting a database a while back.  Basically, I ran out of resources on the server, and I had to adjust the kernel parameters.  Here are the details…

Error message:

ORA-27154: post/wait create failed
ORA-27300: OS system dependent operation:semget failed with status: 28
ORA-27301: OS failure message: No space left on device
ORA-27302: failure occurred at: sskgpcreates

Read More

Script: Check Flash Recovery Usage

I’ve been trying to monitor the archive log usage for our databases, and I came up with this little script.  I thought I would share in case it would help anyone, but also, please correct me if there is a better way or you see anything wrong.

Here’s the basic version.  You can change the database names in the for loop.


tmpfile=/tmp/$(whoami)sql.txt
echo "DB_NAME FILE_TYPE PERCENT_SPACE_USED NUMBER_OF_FILES" > $tmpfile
echo "------- -------------------- ------------------ ---------------" >> $tmpfile
for e in FN91DMO FN91CFG FN91DEV FN91TST
do
 export ORACLE_SID=$e
 sqlplus -s / as sysdba >> $tmpfile <<!
 set head off
 set feedback off
 select '$e' DB_NAME, FILE_TYPE, PERCENT_SPACE_USED, NUMBER_OF_FILES
 from v\$flash_recovery_area_usage
 where PERCENT_SPACE_USED > 0;
 exit;
!
done
sed '/^$/d' $tmpfile
rm $tmpfile

This next version calls a script to get the database names.  For example, I have the databases stored in an XML file, and I built a perl script that would read the XML file and print the database names.


tmpfile=/tmp/$(whoami)sql.txt
echo "DB_NAME FILE_TYPE PERCENT_SPACE_USED NUMBER_OF_FILES" > $tmpfile
echo "------- -------------------- ------------------ ---------------" >> $tmpfile
for e in $(buildDBList)
do
 export ORACLE_SID=$e
 sqlplus -s / as sysdba >> $tmpfile <<!
 set head off
 set feedback off
 select '$e' DB_NAME, FILE_TYPE, PERCENT_SPACE_USED, NUMBER_OF_FILES
 from v\$flash_recovery_area_usage
 where PERCENT_SPACE_USED > 0;
 exit;
!
done
sed '/^$/d' $tmpfile
rm $tmpfile

Finally, this version calls a script to check the status of the database.  If the database is down or temporarily off, it skips that database.


tmpfile=/tmp/$(whoami)sql.txt
echo "DB_NAME FILE_TYPE PERCENT_SPACE_USED NUMBER_OF_FILES" > $tmpfile
echo "------- -------------------- ------------------ ---------------" >> $tmpfile
for e in $(buildDBList)
do
 export ORACLE_SID=$e
 checkDBStatus $e 2>&1 > /dev/null
 if [ $? -eq 0 ]; then
   sqlplus -s / as sysdba >> $tmpfile <<!
   set head off
   set feedback off
   select '$e' DB_NAME, FILE_TYPE, PERCENT_SPACE_USED, NUMBER_OF_FILES
   from v\$flash_recovery_area_usage
   where PERCENT_SPACE_USED > 0;
   exit;
!
 fi
done
sed '/^$/d' $tmpfile
rm $tmpfile

Resources

Creating a Readonly Database User

Here’s a common task: You need to create a database user with read only access.  You have some power users who know how to use SQL, and they are allowed to see all of the data in the system.  You can use these commands to create such a user (in Oracle):

create user PSRO identified by PSRO;
grant create session, select any table, select any dictionary to PSRO;

Note: You can probably find this all over the web, but I wanted to capture it on my blog so that I could find the syntax easier.

Resources

Finding Data in Temp Tables

Here’s a simple little trick for Application Engines that have Temporary Tables assigned.

When you have temporary tables, you don’t know for sure which Temporary Table it is using.  You could write a quick select and change the number on the end until you find the one you are looking for, but here is a slightly quicker method.

Note: This is designed for Oracle, but you could easily change it up to work with SQL Server.

First, build a select statement that will list all of the tables.  We’ll assume our Temporary Table Record is MY_TEMP_TAO.  You can substitute with your specific record.

SELECT 'UNION SELECT ''' || TABLE_NAME || ''' TBL, A.* FROM SYSADM.' || TABLE_NAME || ' A'
FROM DBA_TABLES
WHERE table_name LIKE 'PS_MY_TEMP_TAO%';

Update (thanks to Nicolas): You can avoid having to remove the first UNION if you use something more like this:

SELECT 'SELECT ''' || TABLE_NAME || ''' TBL, A.* ' ||
 'FROM SYSADM.' || TABLE_NAME || ' A' ||
 case when count(*)over()=rownum
 then ';' else ' UNION ' end
FROM ALL_TABLES
WHERE table_name LIKE 'PS_MY_TEMP_TAO%';

The output should look something like this:

UNION SELECT 'PS_MY_TEMP_TAO' TBL, A.* FROM SYSADM.PS_MY_TEMP_TAO A
UNION SELECT 'PS_MY_TEMP_TAO1' TBL, A.* FROM SYSADM.PS_MY_TEMP_TAO1 A
UNION SELECT 'PS_MY_TEMP_TAO2' TBL, A.* FROM SYSADM.PS_MY_TEMP_TAO2 A
UNION SELECT 'PS_MY_TEMP_TAO3' TBL, A.* FROM SYSADM.PS_MY_TEMP_TAO3 A
UNION SELECT 'PS_MY_TEMP_TAO4' TBL, A.* FROM SYSADM.PS_MY_TEMP_TAO4 A
UNION SELECT 'PS_MY_TEMP_TAO5' TBL, A.* FROM SYSADM.PS_MY_TEMP_TAO5 A
UNION SELECT 'PS_MY_TEMP_TAO6' TBL, A.* FROM SYSADM.PS_MY_TEMP_TAO6 A;

You just simply need to delete the first Union to make something like this:

SELECT 'PS_MY_TEMP_TAO' TBL, A.* FROM SYSADM.PS_MY_TEMP_TAO A
UNION SELECT 'PS_MY_TEMP_TAO1' TBL, A.* FROM SYSADM.PS_MY_TEMP_TAO1 A
UNION SELECT 'PS_MY_TEMP_TAO2' TBL, A.* FROM SYSADM.PS_MY_TEMP_TAO2 A
UNION SELECT 'PS_MY_TEMP_TAO3' TBL, A.* FROM SYSADM.PS_MY_TEMP_TAO3 A
UNION SELECT 'PS_MY_TEMP_TAO4' TBL, A.* FROM SYSADM.PS_MY_TEMP_TAO4 A
UNION SELECT 'PS_MY_TEMP_TAO5' TBL, A.* FROM SYSADM.PS_MY_TEMP_TAO5 A
UNION SELECT 'PS_MY_TEMP_TAO6' TBL, A.* FROM SYSADM.PS_MY_TEMP_TAO6 A;

If you know your temp table has the process instance as the key and you know the one you are looking for, you could do something like this:

SELECT * FROM (
     SELECT 'PS_MY_TEMP_TAO' TBL, A.* FROM SYSADM.PS_MY_TEMP_TAO A
     UNION SELECT 'PS_MY_TEMP_TAO1' TBL, A.* FROM SYSADM.PS_MY_TEMP_TAO1 A
     UNION SELECT 'PS_MY_TEMP_TAO2' TBL, A.* FROM SYSADM.PS_MY_TEMP_TAO2 A
     UNION SELECT 'PS_MY_TEMP_TAO3' TBL, A.* FROM SYSADM.PS_MY_TEMP_TAO3 A
     UNION SELECT 'PS_MY_TEMP_TAO4' TBL, A.* FROM SYSADM.PS_MY_TEMP_TAO4 A
     UNION SELECT 'PS_MY_TEMP_TAO5' TBL, A.* FROM SYSADM.PS_MY_TEMP_TAO5 A
     UNION SELECT 'PS_MY_TEMP_TAO6' TBL, A.* FROM SYSADM.PS_MY_TEMP_TAO6 A;
) Z WHERE PROCESS_INSTANCE = 12345

Blog Moving Again

Ok, It is time to move the blog again!  But, this time you shouldn’t have to change your bookmarks!  I am just moving the website to new web host.

The transfer is supposed to be seamless, but I suspect you might see a little downtime over the next week as the domain re-registers and points to the new site.  If it’s not working, please give me some time and check back.

I’ll update you on the other side!

Running Jasper Reports from Java

As a follow-up to my previous post about using iReport, I wanted to write some code that would run the report.  My goal is something that I can launch from PeopleTools.

Below is some Java that will execute the report and build a PDF output.  This class takes the XML data file and the report designed by iReport and produces a PDF out of it.

package net.digitaleagle.psst0101;

import java.io.File;
import java.util.HashMap;
import java.util.Locale;

import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JRParameter;
import net.sf.jasperreports.engine.JasperCompileManager;
import net.sf.jasperreports.engine.JasperExportManager;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.JasperReport;
import net.sf.jasperreports.engine.query.JRXPathQueryExecuterFactory;
import net.sf.jasperreports.engine.util.FileResolver;
import net.sf.jasperreports.engine.util.JRXmlUtils;

import org.w3c.dom.Document;

public class JasperInterface {
	private String dataPath;
	private String basePath;
	private String reportName;
	private String reportOutput;

	public JasperInterface(String dataPath, String basePath, String reportName, String reportOutput) {
		this.dataPath = dataPath;
		this.basePath = basePath;
		this.reportName = reportName;
		this.reportOutput = reportOutput;
	}

	public void run() throws JRException {
		Document data = JRXmlUtils.parse(dataPath);

		HashMap parms = new HashMap();
		parms.put(JRXPathQueryExecuterFactory.PARAMETER_XML_DATA_DOCUMENT, data);
		parms.put(JRXPathQueryExecuterFactory.XML_DATE_PATTERN, "yyyy-MM-dd");
		parms.put(JRXPathQueryExecuterFactory.XML_LOCALE, Locale.ENGLISH);
		parms.put(JRParameter.REPORT_LOCALE, Locale.US);

		FileResolver fileResolver = new FileResolver() {
			 @Override
			 public File resolveFile(String fileName) {
			  return new File(basePath, fileName);
			 }
			};
		parms.put(JRParameter.REPORT_FILE_RESOLVER, fileResolver);

		JasperReport jr = JasperCompileManager.compileReport(basePath + reportName);
		JasperPrint pr = JasperFillManager.fillReport(jr, parms);
		JasperExportManager.exportReportToPdfFile(pr, reportOutput);
	}
}

Here’s some code that can launch the report without needing the JasperReports classes in the classpath.  I originally thought about just putting the jar files into the class directory in the PeopleSoft Home, but Jasper Reports has a number of Jar files.  So, I created a class that had no dependencies on JasperReports.  I tell it the location of the JasperReports installation, and it builds the necessary class path.

package net.digitaleagle.psst0101;

import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;

public class JasperReportRunner {
	private String jasperPath;
	private String dataPath;
	private String basePath;
	private String reportName;
	private String reportOutput;

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		String jasperPath = args[0];
		String dataPath = args[1];
		String basePath = args[2];
		String reportName = args[3];
		String reportOutput = args[4];

		JasperReportRunner jrr = new JasperReportRunner(jasperPath, dataPath, basePath, reportName, reportOutput);
		jrr.run();
	}

	public JasperReportRunner(String jasperPath, String dataPath, String basePath, String reportName, String reportOutput) {
		this.jasperPath = jasperPath;
		this.dataPath = dataPath;
		this.basePath = basePath;
		this.reportName = reportName;
		this.reportOutput = reportOutput;
	}

	public void run() {
		ArrayList urls = new ArrayList();
		File jasperDir = new File(jasperPath);
		addJars(urls, new File(jasperDir, "dist"));
		addJars(urls, new File(jasperDir, "lib"));
		URLClassLoader ucl = new URLClassLoader(urls.toArray(new URL[0]));
		Class jic;
		try {
			jic = ucl.loadClass(this.getClass().getPackage().getName() + ".JasperInterface");
		} catch (ClassNotFoundException e) {
			System.err.println("Could not access JasperInterface class");
			e.printStackTrace();
			return;
		}
		Constructor c = jic.getConstructors()[0];
		Object ji;
		try {
			ji = c.newInstance(dataPath, basePath, reportName, reportOutput);
		} catch (Exception e) {
			System.err.println("Error creating new instance of JasperInterface");
			e.printStackTrace();
			return;
		}
		Method method;
		try {
			method = jic.getMethod("run");
		} catch (Exception e) {
			System.err.println("Could not get run method");
			e.printStackTrace();
			return;
		}
		try {
			method.invoke(ji);
		} catch (Exception e) {
			System.err.println("Could not get execute run method");
			e.printStackTrace();
			return;
		}
	}

	private void addJars(ArrayList urls, File jarDir) {
		if(!jarDir.exists()) {
			System.err.println("Could not find Jasper Jar files in directory: " + jarDir.getAbsolutePath());
			System.err.println("Check installation directory");
			return;
		}
		for(File jarFile : jarDir.listFiles()) {
			if(jarFile.isFile() && jarFile.getName().toLowerCase().endsWith(".jar")) {
				try {
					urls.add(jarFile.toURI().toURL());
				} catch (MalformedURLException e) {
					System.err.println("Error loading jar for class path: " + jarFile.getAbsolutePath());
					e.printStackTrace();
				}
			}
		}
	}

}

Resources

Using iReport with Query Output

Because Oracle has stopped delivering Crystal Reports with PeopleSoft, I heard a few discussions about whether or not to license it for a new installation.  So, it’s an perfect timing to explorer an alternative tool.

Let me introduce JasperReports.  It is open-source, Java-based report generation tool.  The reports are XML files, but they have a tool called iReport that, in my opinion, is very similar to Crystal Reports.

Here’s the descriptions from their website:

iReport:

iReport is the free, open source report designer for JasperReports. Create very sophisticated layouts containing charts, images, subreports, crosstabs and much more. Access your data through JDBC, TableModels, JavaBeans, XML, Hibernate, CSV, and custom sources. Then publish your reports as PDF, RTF, XML, XLS, CSV, HTML, XHTML, text, DOCX, or OpenOffice.

Jasper Reports:

JasperReports is the world’s most popular open source reporting engine. It is entirely written in Java and it is able to use data coming from any kind of data source and produce pixel-perfect documents that can be viewed, printed or exported in a variety of document formats including HTML, PDF, Excel, OpenOffice and Word.

So, as an introduction, let me give you a walk through introduction of using iReport to design a report based on a Query.

Read More