PHP module CodeGen_PECL/ Java JNA

2012 年 1 月 4 日 コメントはありません

PEARにあるCodeGen_PECLで作成する。

http://gihyo.jp/dev/serial/01/php-module

CodeGen_PECL 日本語マニュアル

http://www.m-takagi.org/docs/php/CodeGen_PECL/book1.html

Javaの場合は、JNIが面倒なのでC言語をラップする場合、JNAを使えば簡単かもしれない。

https://github.com/twall/jna#readme

カテゴリー: PHP タグ:

CentOS6.2とPHP(nginx + php-fpm)メモ

2012 年 1 月 4 日 コメントはありません
CentOS6.2とPHP(nginx + php-fpm)メモ
・yumでapacheのMPM(Multi Processing Module)でworkerはインストール可能
・PHPはapacheのworkerを推奨していない。
・FastCGIを推奨している。
CentOS6.2はmcryptがyumでインストールできない

CentOS6.2を最小構成でネットーワークインストールして、その後に以下yumで、nginx+php+php-fpmのビルドが通せる。

 #!/bin/sh # yum install libxml2 # yum install libxml2-devel # yum install bzip2-devel # yum install libcurl-devel # yum install libjpeg-devel libpng-devel freetype-devel # wget http://ftp.riken.jp/Linux/fedora/epel/6/x86_64/epel-release-6-5.noarch.rpm # rpm -ivh xxx # yum --enablerepo=epel install libmcrypt-devel # yum install mysql-devel # yum install aspell-devel # yum install libtidy-devel # yum install libxslt-devel # "./configure" \ "--prefix=/opt/php" \ "--enable-fpm" \ "--with-libdir=lib64" \ "--with-bz2" \ "--with-config-file-path=/opt/php/etc" \ "--with-config-file-scan-dir=/opt/php/etc/php.d" \ "--with-curl=/usr/local/lib" \ "--with-gd" \ "--with-gettext" \ "--with-jpeg-dir=/usr/local/lib" \ "--with-freetype-dir=/usr/local/lib" \ "--with-kerberos" \ "--with-mcrypt" \ "--with-mhash" \ "--with-mysql" \ "--with-mysqli" \ "--with-pcre-regex=/usr" \ "--with-pdo-mysql=shared" \ "--with-pdo-sqlite=shared" \ "--with-pear=/usr/local/lib/php" \ "--with-png-dir=/usr/local/lib" \ "--with-pspell" \ "--with-sqlite=shared" \ "--with-tidy" \ "--with-xmlrpc" \ "--with-xsl" \ "--with-zlib" \ "--with-zlib-dir=/usr/local/lib" \ "--with-openssl" \ "--with-iconv" \ "--enable-bcmath" \ "--enable-calendar" \ "--enable-exif" \ "--enable-ftp" \ "--enable-gd-native-ttf" \ "--enable-libxml" \ "--enable-magic-quotes" \ "--enable-soap" \ "--enable-sockets" \ "--enable-mbstring" \ "--enable-zip" \ "--enable-wddx" 
 yum update yum install php* yum install gcc sudo yum install lynx sudo yum install wget yum install mysql-server yum install gcc.x86_64 gcc-c++.x86_64 make.x86_64 wget.x86_64 yum install pcre-devel.x86_64 yum install openssl.x86_64 openssl-devel.x86_64 yum install libxml2-devel yum install libxml2 yum install bzip2-devel yum install curl yum install libcurl yum install libcurl-devel yum search pcre yum search pcre-devel yum search libjpeg yum install libjpeg-devel libpng-devel freetype-devel yum install libjpeg libpng freetype vi /etc/yum.repos.d/epel.repo yum --enablerepo=epel install libmcrypt yum --enablerepo=epel install libmcrypt-devel yum install mysql-devel yum install aspell yum install aspell-devel yum install libtidy yum install libtidy-devel yum install libxslt-devel yum install opnessh yum install openssh-clients 
カテゴリー: PHP タグ: ,

PHPでGoogle Data API

2011 年 10 月 16 日 コメントはありません

 

 

PHPでGoogle Data APIを操作するために調べたメモ

PHPの場合は、Zend_Gdataをつかうのが簡単そう。

http://code.google.com/intl/ja/apis/gdata/

 

http://code.google.com/intl/ja/apis/gdata/docs/directory.html

http://code.google.com/intl/ja/apis/gdata/docs/auth/oauth.html

 

Zend_Gdata

  • http://framework.zend.com/manual/ja/zend.gdata.html
  • ZendFrameworkに含まれるGoogle Data API用ライブラリ。
  • スタンドアローン版有り。
  • WebアプリケーションをZendFrameworkベースで作っていなくてもライブラリとして使える。
  • 認証は、AuthSub,ClientLogin,OAuthのサンプルがある。
  • 日本語のリファレンス有り。
  • Contact APIなどは、Zend_Gdataでクラス化されたAPIはないが、Zend_Gdata_Queryで自分で全てのコードを書くよりも簡単に作れる。(http://www.ibm.com/developerworks/jp/xml/library/x-phpgooglecontact/)
  • おそらく、新しいHybridというGoogle用OpenID+OAuthは使えない。

Xampp1.7.4の設定ではまりそうなところ

php.ini

include_path = “.;C:\xampp\htdocs\ZendFramework\library;C:\xampp\php\PEAR”

include_path = “.;C:\xampp\htdocs\ZendGdata\library;C:\xampp\php\PEAR”

apacheのhttpd.conf

mod_ssl.so記述を追加。ほかのモジュールはコメントアウトされていたりして記述されているが、mod_sslは追加しなければならない。phpinfo()で、mod_sslの記述があろうが追加しなければデモに含まれているInstallationChecker.phpは動かない。

LoadModule ssl_module modules/mod_ssl.so

 

Zend_Gdataのサンプル実行ではまった箇所

内部のコードで、httpsではなく、httpで接続しようとしているところがある。直接httpsに書き直せばとりあえず動く。
Fatal error: Uncaught exception 'Zend_Gdata_App_HttpException' with message ' in C:\xampp\htdocs\ZendFramework\library\Zend\Gdata\App.php on line 700

Zend_Gdata_App_HttpException: Expected response code 200, got 403
403.4 SSL required in C:\xampp\htdocs\ZendFramework\library\Zend\Gdata\App.php on line 700

コマンドラインで、Calendar.phpを動かすときは、以下のようにUsageでシングルクォートで囲っているが、日時をシングルクォートで囲ってはいけない。

Usage: php Calendar.php createEvent <username> <password> <title> <description> <where> <startDate> <startTime> <endDate> <endTime> <tzOffset>
EXAMPLE: php Calendar.php createEvent <username> <password> 'Tennis with Beth' 'Meet for a quick lesson' 'On the courts' '2008-01-01' '10:00' '2008-01-01' '11:00' '-08'
php -f Calendar.php createEvent アカウント パスワード 'T' 'M' 'O' 2011-10-16 19:00 2011-10-16 20:00 +09
カテゴリー: 未分類 タグ:

avcodec_sample.c for ffmpeg 0.7.1 on Mac OSX 10.7(XCode 4.1)

2011 年 8 月 14 日 コメントはありません
avcodec_sample.c
/* avcodec_sample.c for ffmpeg 0.7.1
 *
 * @see http://www.inb.uni-luebeck.de/~boehme/using_libavcodec.html
 * I read 'Using libavformat and libavcode'. but when use ffmpeg 0.7.1 on MAC OSX 10.7,
 * the clang compiiler has some warning message. so I changed functions from deplicated
 * to current.
 *
 * ChangeLog ********
 *  varialbes declaration like a Java.
 *  when error occured, write log by fprintf function.
 *  new/release(for C++) -> calloc/free(for C)
 *  use sowtware scaling library.
 *
 * make and run sample ********
 * $ make
 * clang -O2 -Wall -I/opt/local/include -I. -c avcodec_sample.c
 * clang -Wall -L/opt/local/lib -L. -o avcodec_sample avcodec_sample.o -lavutil
-lavformat -lavcodec -lswscale -lz
 * $ ./avcodec_sample mp4_h264_aac.mp4
 *
 * my tested environment ********
 * Mac OSX 10.7
 * XCode 4.1 (Apple clang compiler 2.1)
 * ffmpe 0.7.1 (installed by Mac Ports)
 */

#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libswscale/swscale.h"
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include "avcodec_sample.h"

void saveFrame(AVFrame *pFrame, int width, int height, int saveFrameCount) {
	FILE *fp;
	char szFilename[32];

	sprintf(szFilename, "frame%d.ppm", saveFrameCount);
	fp = fopen(szFilename, "wb");
	if (fp == NULL) {
		fprintf(stderr, "Couldn't open file for save.\n");
		return;
	}

	/* Write PPM Header.
     * P6 = Portable Pixcel Map (PPM)
	 * @see http://netpbm.sourceforge.net/doc/ppm.html
	 */
	fprintf(fp, "P6\n%d %d\n255\n", width, height);

	for (int y = 0; y < height; y++) {
		fwrite(pFrame->data[0]+y * pFrame->linesize[0], 1, width*3, fp);
	}
	fclose(fp);
}

int main(int argc, char *argv[]) {
	// Registr all formats and codesc
	av_register_all();

	AVFormatContext *pFormatCtx = NULL;
	const char *filename = argv[1];

	// Open video file
	// dplicated:av_open_input_file
	// if (av_open_input_file(&pFormatCtx, filename, NULL, 0, NULL) != 0) {
	if (avformat_open_input(&pFormatCtx, filename, NULL, NULL) != 0) {
		fprintf(stderr, "Couldn't open file\n");
		return -1;
	}

	// Retrieve stream infomation
	if (av_find_stream_info(pFormatCtx) < 0) {
		fprintf(stderr, "Couldn't find stream infomation\n");
		return -1;
	}

	// Dump infomation about file onto standard error
	// duplicated: dump_format
    // dump_format(pFormatCtx, 0, filename, false);
	av_dump_format(pFormatCtx, 0, filename, false);

	// Find the first video stream
	int videoStream = -1;
	int streamLength = pFormatCtx->nb_streams;
	for (int i = 0; i < streamLength; i++) {
		if (CODEC_TYPE_VIDEO == pFormatCtx->streams[i]->codec->codec_type) {
			videoStream = i;
			break;
		}
	}
	if (videoStream == -1) {
		fprintf(stderr, "Didn't find a video stream\n");
		return -1;
	}

	// Get apointer to the codec context for the video stream
	AVCodecContext *pCodecCtx = pFormatCtx->streams[videoStream]->codec;

	// Find the decoder for the video stream
	AVCodec *pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
	if(pCodec == NULL) {
		fprintf(stderr, "Codec not found\n");
		return -1;
	}

	// Inform the codec that we can handle truncated bitstreams -- i.e.,
	// bitstreams where frame boundries can fall in the middle of packets
	if (pCodec->capabilities & CODEC_CAP_TRUNCATED) {
		pCodecCtx->flags |= CODEC_FLAG_TRUNCATED;
	}

	// Open codec
	if (avcodec_open(pCodecCtx, pCodec) < 0) {
		fprintf(stderr, "Couldn't open codec\n");
		return -1;
	}

	// Hack to correct wrong frame rates that seem to be generated by some
	// codes
	//if (pCodecCtx->frame_rate > 1000 && pCodecCtx->frame_rate_base == 1) {
	//	pCodecCtx->frame_rate_base = 1000;
	//}

	// Allocate video frame
	AVFrame *pFrame = avcodec_alloc_frame();

	// Allocate an AVFrame structure
	AVFrame *pFrameRGB = avcodec_alloc_frame();
	if (pFrameRGB == NULL) {
		fprintf(stderr, "Couldn't allocate frame memory\n");
		return -1;
	}

	// Determin required buffer size and allocate buffer
	int numBytes = avpicture_get_size(PIX_FMT_RGB24, pCodecCtx->width,
 pCodecCtx->height);
	/* changed from 'new' to 'calloc' for C language. */
	// buffer = new uint8_t[[numBytes];
	uint8_t *buffer = calloc(sizeof(uint8_t), numBytes);

	// Assign appropriate parts of buffer to image planes in pFrameRGB
	avpicture_fill((AVPicture *)pFrameRGB, buffer, PIX_FMT_RGB24, pCodecCtx->width,
 pCodecCtx->height);

	// read frames and first five frames to disk
	AVPacket packet;
	int	frameFinished;
	int saveFrameCount = 1;
	static struct SwsContext *swsCtx; /* SWS means SoftWare Scaling */

	/* packet is allocated in the av_read_frame function. */
	while (av_read_frame(pFormatCtx, &packet) >= 0) {
		if (packet.stream_index == videoStream) {
			// duplicated
		// avcodec_decode_video(pCodecCtx, pFrame, &frameFinished, packet.data, packet.size);
			avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet);

			if (frameFinished) {
				/* Allocates and returns a SwsContext. */
				swsCtx = sws_getCachedContext(swsCtx,
						pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt,
						pCodecCtx->width, pCodecCtx->height, PIX_FMT_RGB24,
						SWS_BICUBIC,
						NULL, /* source filter */
						NULL, /* destination filter */
						NULL);

				sws_scale(swsCtx,
					(const uint8_t *const *)pFrame->data,
					pFrame->linesize,
					0, pCodecCtx->height,
					pFrameRGB->data, pFrameRGB->linesize);

				fprintf(stdout, ".");

				// Save the frame to disk;
				if (saveFrameCount <= 5) {
					saveFrame(pFrameRGB,
pCodecCtx->width, pCodecCtx->height, saveFrameCount);
				}
				saveFrameCount++;
			}
		}

		av_free_packet(&packet);
	}

	/* Free the SwsContext */
	sws_freeContext(swsCtx);

	// Free the RGB image
	// delete [] buffer;
	/* changed from 'delete' to 'free' for C language. */
	free(buffer);

	// Free the YUV frame
	av_free(pFrame);

	// Close the codec
	avcodec_close(pCodecCtx);

	// Closes the video file
	av_close_input_file(pFormatCtx);

	return 0;
}
avcodec_sample.h
#ifndef __AVCODEC_SAMPLE__
#define __AVCODEC_SAMPLE__
#endif
Makefile
CC=clang
CFLAGS= -O2 -Wall
INCLUDES= -I/opt/local/include -I.
LDFLAGS= -Wall -L/opt/local/lib -L.
LIBS= -lavutil -lavformat -lavcodec -lswscale -lz
TARGET=avcodec_sample
OBJS=avcodec_sample.o

all:$(TARGET)

$(TARGET):$(OBJS)
	$(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)

clean:
	-rm $(OBJS) $(TARGET) *.ppm

.c.o:
	$(CC) $(CFLAGS) $(INCLUDES) -c $<

avcodec_sample.o:avcodec_sample.h
カテゴリー: 未分類 タグ: , , , ,

librtmp2.3 patch

2011 年 8 月 9 日 コメントはありません

rtmpdumpで、./librtmpはそのままlibrtmpで、ルートディレクトリはツール群というのがわかった。ios-static-librariesとlibrtmpをうまくXCode4のプロジェクトにすればarmv7用にコンパイルできそう。

akamai用パッチ

http://web.archiveorange.com/archive/v/5hTZatyBvFLEYP9IdWG8

authenticationパッチ

http://web.archiveorange.com/archive/v/5hTZaZ61dw95eOSpIxgv

ffmeg configure with librtmp for iPhoneOS4.3, armv7

2011 年 8 月 8 日 コメントはありません
$ ./configure --cc=/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/gcc
--as='gas-preprocessor.pl /Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/gcc'
--sysroot=/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS4.3.sdk
--extra-ldflags=-L/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS4.3.sdk/usr/lib/system
--target-os=darwin
--arch=arm
--cpu=cortex-a8
--extra-cflags='-arch armv7 -I../rtmp/'
--extra-ldflags='-arch armv7 -L../rtmp/'
--enable-pic
--enable-cross-compile
--disable-ffmpeg
--disable-ffplay
--disable-ffserver
--disable-ffprobe
--disable-debug
--disable-shared
-enable-static
--disable-muxers
--disable-demuxers
--disable-filters
--enable-muxer=mov --enable-muxer=flv
--enable-demuxer=mov --enable-demuxer=flv
--enable-decoder=h264 --enable-decoder=mov
--enable-encoder=mjpeg --enable-decoder=mjpeg
--enable-parser=mov --enable-parser=flv
--enable-librtmp
--extra-libs='../rtmp/lib/librtmp.a'
--disable-doc

ERROR: librtmp not found or RTMP_Socket() missing, librtmp version must be >= 2.2.f

If you think configure made a mistake, make sure you are using the latest
version from SVN.  If the latest version fails, report the problem to the
ffmpeg-user@mplayerhq.hu mailing list or IRC #ffmpeg on irc.freenode.net.
Include the log file "config.log" produced by configure as this will help
solving the problem.

Mac OSX 10.7(Lion) + XCode4.1 + iOS 4.3 でiPhone向け(armv7)のffmpegを作るためのconfigure。librtmpを除外すればconfigureを成功することができるようになった。Red5の場合はlibrtmpをなんとかしないといけない。

http://stackoverflow.com/questions/5516170/iphone-sdk-4-3-libav-compiling-problem

librtmpを修正しないと駄目。あと、librtmpでつかうarmv7用のstatic libraryはhttp://code.google.com/p/ios-static-libraries/で公開されているものが使える。

gas(GNU Assembler)は、OSXの場合gas-preprocessor.pl(https://github.com/yuvi/gas-preprocessor)を使う。これは、/usr/local/bin/に置いた。

重たい処理を孫スレッドで実行し、子スレッドは指定ミリ秒数待機、親スレッドはそのまま処理を完了させるサーブレット。

2011 年 7 月 31 日 コメントはありません

package org.oklab.timeoutsandbox;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * CallingTaskWithRequestTimeoutWaitingServlet.
 *
 * 重たい処理を孫スレッドで実行し、子スレッドは指定ミリ秒数待機、親スレッドはそのまま処理を完了させる
 * サーブレット。
 *
 * 一般的に、HTTP通信でリクエストのタイムアウトを指定する場合、クライアント側で指定する。
 * たとえばクライアントで、HTTPのリクエストタイムアウトを5秒に指定した場合に、6秒経過したら、
 * クライアント側は"クライアント側で"タイムアウトと認識し、エラー処理に入る。
 *
 * タスクスケジューラなどを導入して、クライアント側のエラー処理時に停止要求を送信するか、
 * あらかじめ、サーバサイドで、重たい処理処理タイムアウト時間を持たせないと、処理が終わるまで
 * サーバサイドプログラムは走り続ける事になる。
 *
 * このプログラムは、あらかじめタイムアウト時間を指定する実装方法。また、他の言語でも概念を流用できる
 * ように、スレッドベースで書いている。Java5から</code>java.util.concurrent<code>並列処理ライブラリがあるので
 * 以下のような実装であればもっと簡単に実装できる。
 *
 * <pre><code>
 * ExecutorService executor = Executors.newSingleThreadExecutor();
 *     try {
 *         executor.invokeAll(Arrays.asList(new Task()), 2, TimeUnit.SECONDS);
 *     } catch (InterruptedException e) {
 *     e.printStackTrace();
 * }
 * //executor.shutdown();
 * </code></pre>
 *
 * また、別の実装方法としては、タスクのスケジュール機能を導入する方法がある。、この実装の場合は後から
 * タスクの停止も容易にできる。これもJavaの場合は、<code>java.util.concurrent.ScheduledExecutorService</code>
 * で実装が可能。
 *
 * <h2>非同期?</h2>
 * 非同期で、孫スレッドの結果を返していない。あくまでも、重たい処理を別スレッドで実現したかった。
 * 非同期通信はservlet3.0で実装可能。
 *
 * <h2>なぜ親子孫の構造なのか?</h2>
 * 親スレッドでThread.joinを呼び出すと親スレッドが待機してしまうため親スレッドが完了できなかった。
 *
 * <h2>孫スレッド(タスク)の結果は返せないのでは?</h2>
 * 重たい処理を別スレッドで実現したかっただけなので、処理結果をクライアントに返す処理は実装していない。
 * この実装をベースに結果を返すようにするか。<code>executor.invokeAll</code>の戻り値を使えば
 * よいが、その場合、servlet3.0で非同期の実装を考慮したほうがよいはず。
 *
 * @author Satoshi Okita satoshiokita@gmail.com
 * @version 1.0
 * @since 2011/07/31
 */
public class CallingTaskWithRequestTimeoutWaitingServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
	/**
	 * タイマー子スレッドを
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		System.out.println("BEGIN doGet***********");
		response.setContentType("text/html");
		response.setCharacterEncoding("utf-8");
		PrintWriter out = response.getWriter();

		log("main thread:" + Thread.currentThread().getId() + Thread.currentThread().getName());

		Thread TaskTimeMonitor = new Thread(new Runnable() {
			@Override
			public void run() {
				String threadInfo = Thread.currentThread().getId() + Thread.currentThread().getName();
				log("BEGIN child thread:" + threadInfo);

				Thread taskT = new Thread(new ConvertTask());
				taskT.start();
				final long taskTimeoutMillis = 10 * 1000;
				try {
					log("wait task thread 10s:"+ threadInfo);
					taskT.join(taskTimeoutMillis);
					log("after wait task thread 10s:"+ threadInfo);
				} catch (InterruptedException e) {
					e.printStackTrace();
				} finally {
					if (taskT.isAlive()) {
						log("timelimit! terminate child task by " + threadInfo);
						taskT.interrupt();
					}
				}
				log("BEGIN end  thread:" + threadInfo);
			}
		});
		TaskTimeMonitor.start();

		out.print("<html><body>");
		out.print(getClass().getSimpleName());
		out.print("</body></html>");
		out.flush();
		out.close();
		log("END   doGet");
	}
}

class ConvertTask implements Runnable {
	@Override
	public void run() {
		System.out.println("BEGIN task thread:" + Thread.currentThread().getId() + Thread.currentThread().getName());
		try {
			final long MAX_SIZE = 100000;
			for (int i = 0; i < MAX_SIZE; i++) {
				System.out.println("task thread:" + Thread.currentThread().getId() + Thread.currentThread().getName() + " COUNT=" + i);
				Thread.sleep(1000);
			}
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("END  task thread:" + Thread.currentThread().getId() + Thread.currentThread().getName());
	}
}
カテゴリー: Java タグ:

重たい処理を子スレッドで実行し、親スレッドは指定ミリ秒数待機する同期型サーブレット

2011 年 7 月 31 日 コメントはありません
package org.oklab.timeoutsandbox;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * SyncRequestTimeoutWaitingServlet.
 *
 * 重たい処理を子スレッドで実行し、親スレッドは指定ミリ秒数待機する同期型サーブレット。
 *
 * 一般的に、HTTP通信でリクエストのタイムアウトを指定する場合、クライアント側で指定する。
 * たとえばクライアントで、HTTPのリクエストタイムアウトを5秒に指定した場合に、6秒経過したら、
 * クライアント側は"クライアント側で"タイムアウトと認識し、エラー処理に入る。
 *
 * タスクスケジューラなどを導入して、クライアント側のエラー処理時に停止要求を送信するか、
 * あらかじめ、サーバサイドで、重たい処理処理タイムアウト時間を持たせないと、処理が終わるまで
 * サーバサイドプログラムは走り続ける事になる。
 *
 * このプログラムは、あらかじめタイムアウト時間を指定する実装方法。また、他の言語でも概念を流用できる
 * ように、スレッドベースで書いている。Java5から</code>java.util.concurrent<code>並列処理ライブラリがあるので
 * 以下のような実装であればもっと簡単に実装できる。
 *
 * <pre><code>
 * ExecutorService executor = Executors.newSingleThreadExecutor();
 *     try {
 *         executor.invokeAll(Arrays.asList(new Task()), 2, TimeUnit.SECONDS);
 *     } catch (InterruptedException e) {
 *     e.printStackTrace();
 * }
 * //executor.shutdown();
 * </code></pre>
 *
 * また、別の実装方法としては、タスクのスケジュール機能を導入する方法がある。、この実装の場合は後から
 * タスクの停止も容易にできる。これもJavaの場合は、<code>java.util.concurrent.ScheduledExecutorService</code>
 * で実装が可能。
 *
 * @author Satoshi Okita satoshiokita@gmail.com
 * @version 1.0
 * @since 2011/07/31
 */
public class SyncRequestTimeoutWaitingServlet extends HttpServlet {
    /**
     * シリアルバージョンUID.
     */
    private static final long serialVersionUID = 1L;
    /**
     * 処理タイムアウトのミリ秒で、デフォルトは、5000ミリ秒(5秒).
     */
    private static final long PROCESS_TIMEOUT_MILLIS = 5 * 1000;

    /**
     * 重たい処理を子スレッドで実行し、親スレッドは指定ミリ秒数待機する。
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        log("BEGIN doGet");
        String threadInfo = Thread.currentThread().getId() + Thread.currentThread().getName();
        log("実行スレッド(親スレッド):" + threadInfo);

        /*
         * 重たい処理を行うタスク用の子スレッド。
         * 面倒なのでクラスファイルを用意せずここに書いた。
         */
        Thread taskT = new Thread(new Runnable() {
            @Override
            public void run() {
                String threadInfo = Thread.currentThread().getId() + Thread.currentThread().getName();
                System.out.println("BEGIN child thread:" + threadInfo);
                try {
                    /* ダミータスク */
                    final int TASK_SECONDS = 2;
                    for (int i = 0; i < TASK_SECONDS; i++) {
                        Thread.sleep(1000); /* 1秒スリープ */
                        System.out.println(threadInfo + "COUNT=" + i);
                    }
                    System.out.println("");
                } catch (InterruptedException e1) {
                    System.out.println("親スレッドからの割り込み要求を受け付けた。" + threadInfo);
                    e1.printStackTrace();
                }
                System.out.println("END   child thread:" + threadInfo);
            }
        });
        taskT.start();

        /* PROCESS_TIMEOUT_MILLISで指定した秒数待機する。待機後まだ、子スレッドが存在する場合は
         * 割り込み要求をして子スレッドを停止する。
         */
        try {
            log("" + (PROCESS_TIMEOUT_MILLIS/1000) + "秒待機" + threadInfo);
            Thread.currentThread().join(PROCESS_TIMEOUT_MILLIS);
            if (taskT.isAlive()) {
                log("処理時間が" + (PROCESS_TIMEOUT_MILLIS/1000) + "秒超えたので子スレッドへ割り込み(停止)" + threadInfo);
                taskT.interrupt();
            } else {
                log("子スレッドが" + (PROCESS_TIMEOUT_MILLIS/1000) + "秒以内に処理を終えたので割り込み(停止)しない" + threadInfo);
            }
        } catch (InterruptedException e) {
            log("システムの割り込み検知");
        }

        /* 出力 */
        response.setContentType("text/html");
        response.setCharacterEncoding("utf-8");
        PrintWriter out = response.getWriter();
        out.print("<html><body>");
        out.print(getClass().getSimpleName());
        out.print("</body></html>");
        out.flush();
        out.close();

        log("END   doGet");
    }
}
カテゴリー: Java タグ:

CentOS5.5でtomcat5-5.5.23-0jpp.9.el5_5.i386にアップデートするとTomcatが起動しない問題

2010 年 9 月 9 日 コメントはありません

CentOS5.5でtomcat5-5.5.23-0jpp.9.el5_5.i386にアップデートするとTomcatが起動しない問題

現象

定期的に手動でyum updateを行っているのですが、tomcat5-5.5.23-0jpp.9.el5_5.i386にアップデートしたら、Tomcatが正常に起動しなくなりました。/var/log/tomcat5/catalina.outを確認すると以下スタックトレースを確認できました。

2010/09/09 12:09:13 org.apache.catalina.startup.Catalina start

致命的: Catalina.start:
LifecycleException:  Error initializaing :  java.lang.NullPointerException
        at org.apache.catalina.core.StandardContext.start(StandardContext.java:3986)
        at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1014)
        at org.apache.catalina.core.StandardHost.start(StandardHost.java:736)
        at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1014)
        at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:443)
        at org.apache.catalina.core.StandardService.start(StandardService.java:448)
        at org.apache.catalina.core.StandardServer.start(StandardServer.java:700)
        at org.apache.catalina.startup.Catalina.start(Catalina.java:552)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:295)
        at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:433)
2010/09/09 12:09:13 org.apache.catalina.startup.Catalina start

公式サイトにバグ報告がされているので、https://bugzilla.redhat.com/show_bug.cgi?id=623465そのうちCentOSにも反映されると思います。

とりあえずの対応方法。

server.xmlの確認

/etc/tomcat5/server.xmlのContext要素を確認。存在する場合はコメントアウト。

以下の例では、OKLabDevLinkのコンテキストをコメントアウトしています。デフォルトでは、/etc/tomcat5/Catalina/localhostの各Webアプリケーションのコンテキストファイル(この場合はOKLabDevLink.xml)を初期設定ファイルとして認識するので、現在は/etc/tomcat5/server.xmlにContext要素を書く必要はありません。

また、2010/07/30ごろのバックアップされたserver.xmlを確認するとContext要素が書かれていませんでした。いままで何回かTomcatのアップデートを行っていますが、その際にyumが自動でファイル修正を行ったようです。

49       <Host
50           appBase="webapps"
51           name="localhost">
52 <!--
53         <Context
54             path="/OKLabDevLink">
55           <Listener className="org.apache.catalina.startup.TldConfig"/>
56           <WatchedResource>/usr/share/tomcat5/conf/context.xml</WatchedResource>
57         </Context>
58 -->
59       </Host>

各コンテキスト(Webアプリケーション)の設定ファイルを確認

/etc/tomcat5/Catalina/localhostにある各コンテキストの設定ファイルを確認。path要素を削除。

変更前

<?xml version="1.0" encoding="UTF-8"?>
    <Context path="/DnDServer" docBase="DnDServer"
    crossContext="true"
    reloadable="true">
    <?xml version="1.0" encoding="UTF-8"?><Context    crossContext="true"    reloadable="true">

変更後

<?xml version="1.0" encoding="UTF-8"?>
    <Context
    crossContext="true"
    reloadable="true">
    <?xml version="1.0" encoding="UTF-8"?><Context    crossContext="true"    reloadable="true">

この例では、path要素とdocBase要素を削除しています。TomcatのWebアプリケーションであるadmin.xmlやmanager.xmlを確認するとdocBase要素は記述されているので削除する必要はないと思われます。私の場合は他のWebアプリケーションにもdocBase要素を指定していないので、削除しただけです。

再起動

あとは、/etc/init.d/tomcat5 restartで再起動して、/var/log/tomcat5/catalina.outで例外スタックとレースが発生しないことを確認してください。

参考:

カテゴリー: サーバ構築, 環境設定 タグ: ,

Oracle JDeveloper 11gのチュートリアルと学習

2010 年 2 月 7 日 コメントはありません

Java の開発は 統合開発環境として Eclipse を使うのが一般的です。私も仕事でよく使うのですが、今後使用するかもしれないので、 休日中に、Oracle JDeveloper 11g  調べてみました。

Oracle は数年前に Weblogic アプリケーションサーバで有名な BEA システムズ を買収し、最近 サンマイクロシステムズを買収しました。そのため Eclipse と比較すると、IDE にWeblogicが組み込まれている点と、Oracle 用の SQL開発環境が組み込まれている点が Eclipse に対するメリットと感じました。 Weblogic向けのEJB関係の自動生成機能などは非常に便利で、EJB2.0 のころと比べると作る敷居がかなり下がった印象でした。

デメリットは、Eclipse のような豊富なプラグインでカスタマイズできないことと、日本語ドキュメントの少なさを感じました。そのため、Weblogic と Oracle を使う前提だと強力な統合開発環境ですが、開発は、Tomcat アプリケーションサーバを使ったり、Seaserフレームワークなど様々なフレームワークを使う場合は Eclipse のほうが使いやすいです。

学習するドキュメントについては、英語ですが、Oracle.com – Getting Started: Java が参考になります。はじめは、Oracle JDeveloper 11g のドキュメントを Google でがんばって探したのですが入門レベルの日本語ドキュメントはないようでした。英語は大変ですが上記ドキュメントで学習したほうが早いです。また、このチュートリアルはスクリーンショットがあるので何とかなると思います。

チュートリアルのはじめの章(Step 3)で、簡単な Java のクラスを作成したり、リファクタリング、ビルド、デバッグなどを通して、その作業で、JDeveloper がどのような動きをするのかが理解できます。 休日にVisual Studio 、NetBeans を使ったりしてある程度いろいろな統合開発環境には慣れているのですが、Weblogic がどのように統合されているかなどを理解するためにも、はじめの章は試してみたほうがよいです。所要時間は30分ぐらいです。

また、Step 4 の Build the business logic for an application using EJB 3.0 で Weblogic向けの EJB3.0 と JPA が学習できます。所要時間はこれも30分くらいです。

私の場合はここまでで1時間30分ぐらい掛かりましたが Step 4まで行えば 今後 JDeveloper で J2EE 側の実装が可能になります。Step 5まで行えば、Web層を含めて開発ができるようになると思います。Step 6 ではさらに SOA の学習となります。

今回 JDeveloper 11g をはじめて使ってみましたが、やはり自社製品との連携機能は強力でした。Oracle データベースは、CPUなどのハードウェアの制約がありますが、Oracle XE が無償で使えるので、Weblogic も個人向けに 無償版ライセンスができると、もっと JDeveloper と Weblogic のユーザが増えそうですね。

カテゴリー: Java, データベース タグ: , ,