2018년 2월 4일 일요일

Creating CRC32 Hex string

public String getCRC32HexaString(String paramString) throws Exception  {
  byte bytes[] = paramString.getBytes(DEFAULT_CHARSET);
  Checksum checksum = new java.util.zip.CRC32();
  checksum.update(bytes, 0, bytes.length);
  long checksumValue = checksum.getValue();
  return Long.toHexString(checksumValue);
}

Mysql 성능튜닝

 innodb_flush_log_at_trx_commit
Command-Line Format--innodb_flush_log_at_trx_commit[=#]
System VariableNameinnodb_flush_log_at_trx_commit
Variable ScopeGlobal
Dynamic VariableYes
Permitted ValuesTypeenumeration
Default1
Valid Values0
1
2
Controls the balance between strict ACID compliance for commit operations, and higher performance that is possible when commit-related I/O operations are rearranged and done in batches. You can achieve better performance by changing the default value, but then you can lose up to a second of transactions in a crash.
  • The default value of 1 is required for full ACID compliance. With this value, the contents of the InnoDB log buffer are written out to the log file at each transaction commit and the log file is flushed to disk.
  • With a value of 0, the contents of the InnoDB log buffer are written to the log file approximately once per second and the log file is flushed to disk. No writes from the log buffer to the log file are performed at transaction commit. Once-per-second flushing is not 100% guaranteed to happen every second, due to process scheduling issues. Because the flush to disk operation only occurs approximately once per second, you can lose up to a second of transactions with any mysqld process crash.
  • With a value of 2, the contents of the InnoDB log buffer are written to the log file after each transaction commit and the log file is flushed to disk approximately once per second. Once-per-second flushing is not 100% guaranteed to happen every second, due to process scheduling issues. Because the flush to disk operation only occurs approximately once per second, you can lose up to a second of transactions in an operating system crash or a power outage.
  • InnoDB's crash recovery works regardless of the value. Transactions are either applied entirely or erased entirely.
For the greatest possible durability and consistency in a replication setup using InnoDB with transactions, use innodb_flush_log_at_trx_commit=1 and sync_binlog=1 in your master server my.cnf file.

Mysql InnoDB 관련 설정

innodb_data_file_path
Data File(Tablespace)의 속성을 정의한다.
[Data file path]파일명:파일크기:autoextend:max:파일최대크기;
파일 구분은 ';'이고 속성 구분은 ':'이다.

innodb_autoextend_increment
Data File(Tablespace)이 확장될 때 증가되는 Size(MB) (default=8M)

innodb_additional_mem_pool_size
default : 2M
Data Dictionary 정보를 보관하기 위한 Memory Size.

innodb_buffer_pool_size
default : 8M
index 및 raw data Cache 용 Memory Size를 의미하며 Maximum Size는 Real Memory의 80%까지 정의 가능하다. 하지만, Memory Paging을 최소화 할 수 있는 Size가 적당하다. 참고로 Oracle의 권고 SGA Size는 Real Memory의 50%이다. 32 Bit O/S의 경우 Addressing 특성 상 Maximum 4G이므로 O/S 및 다른 용도의 Memory를 감안하여 이보다 작게 정의해야 한다.

innodb_flush_method
Disk I/O Buffer의 사용 여부.
일반적으로 Disk I/O가 발생하면 그 즉시 Disk에 반영되지 않고 Memory에 Caching되었다가 일정 Size이상이 되면 그 때 Disk에 Physically 반영되는데, 이러한 과정 없이 즉시로 Disk에 반영 시키는 Option이다.
[O_DIRECT] Cache Write 시 Disk에도 동일하게 반영 시킨다.
[O_DSYNC]

innodb_flush_log_at_trx_commit
Commit 시 Commit Log를 Log File에 어떻게 기록할지를 지정한다.
[0] Log Buffer가 꽉 차거나 Flush Log가 발생할때 Log File에 기록
[1] Commit이 발생할 때 마다 Log File에 기록
[2] 1초마다 Log File에 기록

innodb_log_file_size
트랜잭션을 기록하는 로그 파일의 크기를 결정하는 옵션으로  로그파일은 무한정 계속 커지는 것이 아니라 일정한 크기와 갯수를 가지고 순환식으로 처리된다.
보통 일반적으로 innodb_buffer_pool_size 의 15% 정도로 설정한다.
만약 메모리가 1GB이면 innodb_buffer_pool_size = 512M 이고, innodb_log_file_size = 80M 이다.

innodb_log_buffer_size
로그 파일을 기록하기 위한 Buffer Size로 Transaction이 작거나 거의 없다면 크게 잡는것은 낭비이다.
보통 1M~8M 사이로 설정.

innodb_log_archive
Log File의 Archive화 여부로 복구 시 Log File을 사용하므로 설정할 필요가 없음.

innodb_file_per_table
Table 마다 별도의 Data File을 가지게하는 옵션으로 하나의 Tablespace에는 하나의 Table Data만 저장한다. 단, 단점은 Data와 Index가 동일 Tablespace(Data File)에 저장된다는 것이다.


리눅스 오픈소스 바이러스 백신 CLAM

https://www.centosblog.com/enable-epel-repo-on-centos-5-and-centos-6/

어떤 젊은이의 어떤 생각

사람은 결국 쾌락으로 움직이는 것이다. 그저 뇌 속의 전기신호에 평생 좌지우지될 뿐이다.
가능한 돈이 들지 않는 쾌락을 찾아낸다. 돈이 드는 취미나 오락은 갖지 않는다.
인터넷을 최대한 활용하여 모든 오락 및 생활정보 수집은 기본료만으로도 끝낼 수 있도록 한다.
비금전적, 비물질적인 행복관을 추구해라. 쾌락에 귀천은 없다. 각자가 좋아하는 쾌락을 추구하면 충분하다.

검소검약을 항상 유념한다.
꿈은 꾸지 않는다. 희망도 갖지 않는다.
사치를 부리지 않는다. 허세를 부리지 않는다.
집착하지 않는다.
타인과 비교하지 않는다. 평균을 요구하지 않는다.
여분의 소비는 하지 않고, 물건은 오래 소중히 사용한다.
누군가에게 기대를 갖지 않는다. 세상에 무언가를 요구하지 않는다.
지금 소유한 것 이외는 갖지 않는다. 사지도 않는다. 사실 별로 필요도 없다.
무조건 경쟁심이나 질투심을 갖지 않는다. 지는 것이 이기는 것이라 생각한다.

부자들의 경쟁 권유에는 올라타지 않는다.
국가, 사회, 조직, 개인에게 충성을 맹세하지 않는다.
상식이나 도덕, 윤리, 유행 등 항상 모든 것을 의심하는 시선을 가진다.
다른 사람이나 사회에 대해 비판적인 시선은 보내지만 경쟁에는 참가하지 않는다.
노예/노동형 기업에서는 일하지 않는다. 자신이 일한 분량의 절반 정도는 승리자들에게 착취당하고 있다.
인간을 노예나 물건처럼 취급하고, 이런저런 속임수를 쓰는 모럴이 결핍된 기업이나 단체에는 돈을 쓰지 않는다.
받는 보수 이상의 일은 하지 않는다. 도를 넘은 봉사, 노력, 인내, 종속, 성실, 사람이 좋다 따위는 절대 미덕이 아니다.
모든 사건에 대해서 무관심, 방관자적 입장을 관철해라. 다만 역사나 시사 등은 잘 공부하여 지배층의 수작에 넘어가지 않도록 대비한다.

부패한 종교관에 돈을 뺏기지 말아라. 종교는 개인적인 범주라면 믿어도 좋지만, 종교 단체에는 절대 돈을 쓰지 않는다.
쓸데없는 친구는 최대한 기피한다. 쓸데없는 회식이나 다과회의 권유는 낭비의 원인이다.
무의미한 브랜드 옷 같은 것에 흥미를 갖지 않는다.
식사는 싼 식당에서 적당히 해결한다. 고급 음식점에서 쓸데없는 낭비는 하지 않는다.
가능한 한 부모님과 함께 산다. 그렇지 않을 경우에는 룸메이트를 구해서 돈을 나눠낸다.

빚을 지지 않는다. 카드도 만들지 않는다.
금융기관에 예금을 하지 않는다. 돈을 그저 장농에 잘 모셔놓는다.
차는 경차로도 충분하다. 가능하면 차 없이 자전거를 탄다.
명품, 고급차, 집은 포기한다. 사지 않는다. 갖고 싶어하지도 않는다.
술, 담배, 도박은 하지 않는다. 또한 주식이나 현물거래 등에 손을 대지 않는다.
부동산 소개소, 주인, 건설업계, 은행, 가전업계 등에 쓸데없는 돈을 소비하지 않는다.
필요한 때 이외에는 가급적 외출하지 않는다. 외출할 때는 필요한 최저한의 돈만 소지하고, 외식이나 예정에 없는 길로 돌아다니지 않는다.

신문은 인터넷, 책은 서점이나 도서관에서 공짜로 끝낸다.
자본주의 사회는 광고로 도배된 세계. 유혹에 지지 말자.
아침을 가급적 먹는다. 폭음이나 폭식은 하지 않는다. 심신의 건강을 유지 한다.

관혼상제에 돈을 들이지 않는다. 동거, 결혼, 출산 등 생산성을 재촉하는 사회 활동에는 가담하지 않는다.
결혼은 하지 않는다. 결혼해도 아이는 만들지 않는다. 아이 한 명 당 평균 4억원 이상의 지출이다. 요즘 세상에 부모가 되는 것은 제정신이 아니다.
성욕은 수음으로 해소하자. 여성은 정히 필요하다면 업소의 여성으로 적당히 때우자.
주변의 잘 나가는 사람이나 이성의 환심을 사고자 돈을 쓰지 않는다.

제행은 무상이라는 것을 안다.
잘살든 못살든 결국 도착하는 것은 죽음이다.
학력도, 돈도, 여자도, 추억도, 결국 묘지로 갖고 갈 수는 없다.



“오늘의 젊은이들은 ‘내일이 더 나아질 것이다’라는 생각을 믿지 않는다. 그들의 눈앞에 펼쳐져 있는 것은 그저 끝나지 않는 일상일 뿐이다. 그래서 지금 ‘행복하다’고 말할 수 있다. 다시 말해 인간은 미래에 대한 희망을 잃었을 때 비로소 행복해질 수 있다.”

Myabtis에서 컬럼값이 null인 경우도 null로 조회하는 설정

myabtis.xml에서 다음과 같이 설정

<settings>
...
<setting name="callSettersOnNulls" value="true"/>
...
</settings>

오라클 실행계획 보는법

--select * from table(DBMS_XPLAN.DISPLAY);
--explain plan for
SELECT 1 FROM DUAL

linux CPU 현재 사용량 조회

sar 1 1 | grep 'Average' | awk '{print $3"+"$5"="$3'+'$5}'

주가가 퍽락해쓸때 혈액형별 대응.

O형
ㅡ ㅆㅂ 한마디하고 바로 패대기 친다.
A형
ㅡ내가 사서 퍽락한건가? 하면서 조낸
고민한다.
B형
ㅡ오르던 떨어지던 비교적 관심없다.
목표가 혹은 손절가에 패대기친다.
AB형
ㅡ주가가 왜떨어졌는지 조낸 분석하고
고민하다가 2차퍽락을 맛본다.
그리고 또 조낸분석하다 3차...

xuggler 로 스트리밍 정보 및 read

package com.oopscraft.test.generator;
import com.xuggle.xuggler.ICodec;
import com.xuggle.xuggler.IContainer;
import com.xuggle.xuggler.IStream;
import com.xuggle.xuggler.IStreamCoder;

public class VideoInfo {

    private static final String filename = "rtmp://101.79.242.18/ch14/ch14_800.stream?id=3101&sa=67e56ce383fa39821e1dbe9d6445fcf5aa0f6e83fc5f719b64717325ac30693143dc407c681599bb365d38c1140db122b96fc58ed1e83a553c3a3ecbda295b2d";

    public static void main(String[] args) {
        // first we create a Xuggler container object
        IContainer container = IContainer.make();

        // we attempt to open up the container
        int result = container.open(filename, IContainer.Type.READ, null);

        // check if the operation was successful
        if (result<0)
            throw new RuntimeException("Failed to open media file");

        // query how many streams the call to open found
        int numStreams = container.getNumStreams();

        // query for the total duration
        long duration = container.getDuration();

        // query for the file size
        long fileSize = container.getFileSize();

        // query for the bit rate
        long bitRate = container.getBitRate();

        System.out.println("Number of streams: " + numStreams);
        System.out.println("Duration (ms): " + duration);
        System.out.println("File Size (bytes): " + fileSize);
        System.out.println("Bit Rate: " + bitRate);

        // iterate through the streams to print their meta data
        for (int i=0; i<numStreams; i++) {

            // find the stream object
            IStream stream = container.getStream(i);

            // get the pre-configured decoder that can decode this stream;
            IStreamCoder coder = stream.getStreamCoder();

            System.out.println("*** Start of Stream Info ***");
            System.out.printf("stream %d: ", i);
            System.out.printf("type: %s; ", coder.getCodecType());
            System.out.printf("codec: %s; ", coder.getCodecID());
            System.out.printf("duration: %s; ", stream.getDuration());
            System.out.printf("start time: %s; ", container.getStartTime());
            System.out.printf("timebase: %d/%d; ",
stream.getTimeBase().getNumerator(),
tream.getTimeBase().getDenominator());
System.out.printf("coder tb: %d/%d; ",
                 coder.getTimeBase().getNumerator(),
                 coder.getTimeBase().getDenominator());
            System.out.println();

            if (coder.getCodecType() == ICodec.Type.CODEC_TYPE_AUDIO) {
                System.out.printf("sample rate: %d; ", coder.getSampleRate());
                System.out.printf("channels: %d; ", coder.getChannels());
                System.out.printf("format: %s", coder.getSampleFormat());
            }
            else if (coder.getCodecType() == ICodec.Type.CODEC_TYPE_VIDEO) {
                System.out.printf("width: %d; ", coder.getWidth());
                System.out.printf("height: %d; ", coder.getHeight());
                System.out.printf("format: %s; ", coder.getPixelType());
                System.out.printf("frame-rate: %5.2f; ", coder.getFrameRate().getDouble());
            }

            System.out.println();
            System.out.println("*** End of Stream Info ***");
        }
    }
}

package com.oopscraft.test.generator;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import com.xuggle.xuggler.ICodec;
import com.xuggle.xuggler.IContainer;
import com.xuggle.xuggler.IPacket;
import com.xuggle.xuggler.IStream;
import com.xuggle.xuggler.IStreamCoder;

public class Record {

        public static void main(String[] args) throws Exception {
                IContainer readContainer = IContainer.make();
                IContainer writeContainer = IContainer.make();
                int videoStreamId=0;
                int i = readContainer.open("rtmp://101.79.242.18/ch14/ch14_800.stream?id=3101&sa=6465dbea334f3242be1ebe766e15b3fd9ab267539e5381f261f1962afcf86e31f5d630016195d2bad6b83d710d03f128162d6c79da7bd4af05b2f622255fb92e",IContainer.Type.READ, null, true, false);
                writeContainer.open("header1.flv", IContainer.Type.WRITE, null);

                if (i >= 0) {
                        IStream inVideoStream = readContainer.getStream(0);
                        IStreamCoder inVideocoder = inVideoStream.getStreamCoder();
                        inVideocoder.setCodec(ICodec.ID.CODEC_ID_FLV1);
                        inVideocoder.setTimeBase(inVideoStream.getTimeBase());
                        inVideocoder.setHeight(320);
                        inVideocoder.setWidth(240);
                        IStream outVideoStream = writeContainer.addNewStream(0);
                        outVideoStream.setStreamCoder(inVideocoder);
                        int video = inVideocoder.open();
                        if (video >= 0) {
                                System.out.println("Good videoStream");
                        } else {
                                System.out.println("Wrong videoStream");

                        }

                        IStream inAudioStream = readContainer.getStream(1);
                        IStreamCoder inAudioCoder = inAudioStream.getStreamCoder();
                        inAudioCoder.setCodec(ICodec.ID.CODEC_ID_MP3);
                        inAudioCoder.setSampleRate(44100);
                        inAudioCoder.setTimeBase(inAudioStream.getTimeBase());
IStream outAudioStream = writeContainer.addNewStream(1);
                        outAudioStream.setStreamCoder(inAudioCoder);
                        int audio = inAudioCoder.open();
                        if (audio >= 0) {
                                System.out.println("Good audioStream");
                        } else {
                                System.out.println("Wrong audioStream");
                        }
                        int header = writeContainer.writeHeader();
                        if (header == 0) {
                                System.out.println("good header");
                        } else {
                                System.out.println("wrong header" + header);
                        }
                        IPacket packet = IPacket.make();
File file = new File("data0-1000.manu");
FileChannel wChannel = new FileOutputStream(file, false).getChannel();
ByteBuffer bbuf = null;
long initTS=1000;

while (readContainer.readNextPacket(packet) >= 0 && packet.isComplete()) {
bbuf = packet.getByteBuffer();
if(packet.getTimeStamp()-initTS >= 1000 && packet.isKeyPacket())
{
file = new File("data"+initTS+"-"+packet.getTimeStamp()+".manu");
initTS=packet.getTimeStamp();
wChannel = new FileOutputStream(file, false).getChannel();
}
if(bbuf!=null)
wChannel.write(bbuf);
writeContainer.writePacket(packet);
System.out.println(packet.getTimeStamp());
                        }

                        //writeContainer.writeTrailer();
                        writeContainer.close();
                        wChannel.close();
                } else {
                        System.out.print("Wrong!!!");
                }
        }
}

Proguard ANT Task 를 통한 소스 난독화

<?xml version="1.0" encoding="UTF-8"?>
<project name="generator" default="build" basedir=".">
<property name="versionNumber" value="2.4"/>
<tstamp>
  <format property="buildNumber" pattern="yyyyMMdd" locale="euc,KR"/>
</tstamp>
<property name="src" value="src"/>
<property name="classes" value="classes"/>
<property name="dist" value="dist"/>
<property name="distJar" value="non-obfuscator-light-secure-url-generator-${versionNumber}.${buildNumber}.jar"/>
<property name="obfuscatorJar" value="light-secure-url-generator-${versionNumber}.${buildNumber}.jar"/>

<target name="clean">
<delete dir="${classes}"/>
<delete file="${distJar}"/>
</target>

<target name="compile" depends="clean">
<mkdir dir="${classes}"/>
<javac srcdir="${src}"
encoding="UTF-8"
source="1.7" target="1.7"
destdir="${classes}"
debug="no"
includeantruntime="false">
</javac>
<copy todir="${classes}">
<fileset dir="${src}" includes="*.properties"/>
</copy>
</target>

<target name="build" depends="compile">
<mkdir dir="${dist}"/>
<jar jarfile="${dist}/${distJar}"
basedir="${classes}"
includes="com/gscdn/**/*"
excludes="**/*Test.*"
compress="no"
manifest="Manifest-light-secure-url.mf">
</jar>
<taskdef resource="proguard/ant/task.properties"
classpath="lib/proguard.jar" />
<proguard>
<![CDATA[
-injars ${dist}/${distJar}
-outjars ${dist}/${obfuscatorJar}
-libraryjars ${java.home}/lib/rt.jar
-libraryjars ${java.home}/lib/jce.jar
-keep public class * {
    public protected <fields>;
    public protected <methods>;
}
]]>
</proguard>
</target>

</project>



출처: http://chan77xx.tistory.com/category/?page=2 [超無 - 초무]

Apache Benchmark

ab -n 1000 -c 100 "http://localhost"

traceroute 포트 확인

traceroute -n -p 3306 -T 127.0.0.1

Bytes가 String형식인지 Binary형식인지 여부 정규식을 이용한 간단체크

/**
 * 로깅 가능한 String 메시지로 변환한다.
 * 텍스트 형식으면 텍스트로, 바이너리라고 추정되면 hex 반환.
 * @param message
 * @return
 */
private String convertLogMessage(ByteBuffer message) {
String logMessage = null;
try {
logMessage = new String(ByteBuffer.wrap(message.array(), 0, message.limit()).array(),"UTF-8");
if(Pattern.compile("[^\\x20-\\x7e]").matcher(logMessage).find()) {
logMessage = Hex.encodeHexString(ByteBuffer.wrap(message.array(), 0, message.limit()).array());
}
}catch(Exception ignore){}
return logMessage;
}

저쪽으로 갔어 ㅋㅋㅋ


ANT red-line 플러그인을 이용한 리눅스 RPM패키지 빌드

[JAVA로 작성된 어플리케이션을 RPM으로 배포할 경우 ANT의 RPM 패키징 태스크를 이용하여 빌드 하는 법]
어플리케이션을 RPM패키지로 배포해야되는 경우 linux의 rpmbuild를 이용하여 패키징 시 몇가지 문제점이 발생함.
(한가지 예로 CentOS 6.xx에서 빌드한 RPM패키지의 경우 CentOS 5.xx 에서 설치가 않되는 경우 발생)
이럴 경우 Pure 자바로 작성된 RPM패키지 라이브러리를 사용해보잣~
몇가지 형태로 사용가능하나 여기서는 ANT의 Task로 등록하여 사용하는 방법으로 구현.


RedLine 라이브러리 다운로드하자.
http://redline-rpm.org/usage.html

이클립스 플러그인 설정 및 테스트
1. jar 라이브러리 ecilpse의 plugin 폴더에 복사
2. Preperence > Ant > Runtime 메뉴에서 Classpath > Contributed Entries로 등록

ANT의 build.xml 파일 작성
<project basedir="." xmlns:redline="antlib:org.redline_rpm">
<target name="rpm">
<mkdir dir="dist"/>
<redline:rpm group="Java Development" name="Application.rpm" version="" destination="dist">
<!-- executable jar file -->
<zipfileset prefix="/usr/local/application" file="./Application.jar"/>
<!-- additional config file -->
<rpmfileset prefix="/usr/local/application" file="./config.xml" config="true" noreplace="false" filemode="755" username="root" group="root"/>
<rpmfileset prefix="/teralog/agent" file="./log4j.properties" config="true" noreplace="false" filemode="755" username="root" group="root"/>
<!-- registers init start,stop script -->
<rpmfileset prefix="/etc/rc.d/init.d" file="./GSCDN_TOTMN_AGENT.sh" filemode="755" username="root" group="root"/>
<link path="/etc/rc.d/rc3.d/K02[APPLICATION].sh" target="/etc/rc.d/init.d/[APPLICATION].sh"/>
<link path="/etc/rc.d/rc3.d/S50[APPLICATION].sh" target="/etc/rc.d/init.d/[APPLICATION].sh"/>
</redline:rpm>
<move file="./dist/GSCDN_TOTMN_AGENT--1.noarch.rpm" tofile="./dist/GSCDN_TOTMN_AGENT-linux.rpm"/>
</target>
</project>

아파치 인증이 필요한 패스에 wget으로 파일 다운로드

wget -N --http-user=[사용자명] --http-passwd=[패스워드] http://[리소스 경로명]

아파치 https 설정

vim ./apache/conf/httpd.con
or
vim ./apache/conf/vhosts/home.oopscraft.com.conf

[아래 내용 추가]
RewriteEngine On
RewriteCond %{HTTPS} !=on
RewriteRule ^/?(.*) https://%{SERVER_NAME}/$1 [R,L]

MYSQL 날짜 Dummy 테이블

Mysql에서는 재귀호출함수가 없어서 날짜 더미테이블 생성할때는 이게 제일 간단한듯..

select  dt.yyyymmdd
from    (
        select      curdate() - INTERVAL (a.a + (10 * b.a) + (100 * c.a)) DAY as yyyymmdd
                    ,a.a as aa
                    ,b.a as ba
                    ,c.a as ca
        from        (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as a
        cross join  (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as b
        cross join  (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as c
        ) dt
where dt.yyyymmdd between '2015-07-10' and '2015-07-15'

여자친구에게 군대 진지공사 이해 시키기


이 데칼 정말 빠져든다;;







적금 풍차돌리기?

우연히 적금 풍차돌리기 재테크 무림비법을 발견 (이거 잼있는듯 ^^;)
월 120만원 불입 적금 가입 예정인 경우
한번에 가입하지 않고 다음과 같이 분할하여 가입

1월: 월 10만원불입 적금1 시작
2월: 월 10만원불입 적금2 시작
.
.
11월: 월 10만원불입 적금11 시작
12월: 월 10만원불입 적금12 시작

다음 년도 1월에 적금#1 만기 하여 [원금 + 이자] 통장에 들어옴.
그럼 다시 풍차돌리기 시작. 2월에도 만기 돌아오면 풍차돌리기 시작. 계속...ㄱㄱ
이렇게 되면 가입 1년 후부터는 매달 적금 만기가 돌아옴. 그럼 다시 풍차돌리기 ㄱㄱ
적금 풍차돌리기의 장점은 매달 돌아오는 만기로 재미 UP + 단리가 아닌 복리로 이자수익 창출 인듯.
이거 투자보다는 안정적인 적금을 좋아하시는 분은 추천할만한 재테크 방법인듯.

리눅스 로그파일 종류

# 콘솔 로그
/dev/console
콘솔에 뿌려지는 로그

# 시스템 로그
/var/log/messages
리눅스 커널로그 및 주된 로그

# TCPD로그
/var/log/secure
inetd에 의한 로그

# 메일 로그
/var/log/maillog
sendmail에 의한 로그

# 크론 로그
/var/log/cron
crond에 의한 로그

# 부팅 로그
/var/log/boot.log
시스템 부팅시의 로그

# FTP로그
/var/log/xferlog
FTP로그

# 웹로그
/usr/local/apache/logs/access_log
아파치로그

# 네임서버로그
/var/log/named.log
네임서버(DNS) 로그

Installation of Subversion

Installing Subversion
tar -jxvf subversion-deps-x.x.x.tar.bz2
cd subversion-x.x.x
Now we'll compile the APR first.
cd apr
./configure --prefix=/usr/local/apr
make
make install
cd ..
Next we'll compile APR-UTIL.
cd apr-util
./configure --prefix=/usr/local/apr --with-apr=/usr/local/apr/
make
make install
cd ..
After we're done with APR and APR-UTIL, we'll need to compile NEON.
cd neon
./configure --prefix=/usr/local/neon
make
make install
cd ..
Finally we need to compile subversion with the support for all the we just installed.
./configure --prefix=/usr/local/subversion --with-apxs={Location where you installed apache}/bin/apxs --with-apr=/usr/local/apr/ --with-apr-util=/usr/local/apr-util/ --with-neon=/usr/local/neon/ --with-ssl
make
make install

Creating a user for apache and modifying httpd.conf:
groupadd apache
useradd -g apache -d /usr/local/apache2
After installing apache we need to set ownership of all the files in /usr/local/apache2 to user apache.
chown -Rv apache.apache /usr/local/apache2
Finally we need to set which user the Apache server will be running as.
Edit the default configuration file, or whatever configuration file apache uses to run as.
I am going to assume the configuration file is /usr/local/apache2/conf/httpd.conf.
vi /usr/local/apache2/conf/httpd.conf
Locate the line where it states something like.

User nobody
Group #-1
Make it look like this.

User apache
Group apache

아.. 프로젝트 게시판에 올리고 싶다.


프로젝트를 진행하면서 각 팀들은 자기 입장만 고수.
대략 아래 그림이지 않을까 싶은..

(실제 아래 3가지를 모두 이해할수 있으면 당신은 구루)

대량 데이타 SQL에서의 페이징 처리

가끔 화면 개발에서 대량 테이블 조회를 페이징 처리 시 그냥  rs.next() 로 해서 처리하는 경우가 있는데 그럼 프로그램 되~짐~
아래와 같이 SQL로 조회 시 부터 페이징 처리해서 조회하여야 깔끔~

1. Bind Parameter (바인딩 패라미터)
- :fetchSize : Row count of 1 transaction fetching
- :fetchPage: Number page you want.

2. Query Statement (오라클 기준 Query)
/* PAGING-HEAD */
SELECT * FROM ( SELECT * FROM ROWNUM RN, DAT.* FROM (
/* START-BODY */
SELECT 1 COL1 FROM DUAL UNION ALL
SELECT 2 COL2 FROM DUAL UNION ALL
SELECT 3 COL3 FROM DUAL UNION ALL
SELECT 4 COL4 FROM DUAL
/* END-BODY */
/* PAGING-FOOT */
) DAT WHERE ROWNUM <= (:fetchSize * fetchPage) ) WHERE RN > :fetchSize * (fetchPage -1))

SQL에서의 소계 처리(ROLLUP)

오라클 데이타베이스에서 소계합계처리는 다음과 같이 ROLLUP함수 사용

WITH P AS (
SELECT   '20100901'  AS FM_YMD       -- 시작검색일
        ,'20101231'  AS TO_YMD       -- 종료검색일
FROM DUAL
)
SELECT      /*+ PARALLEL(SND,2) */
            DISTINCT
             SND.SND_TYP        "발송유형"
            ,SND.SND_YMD        "발송일자"
            ,COUNT(*)           "발송수량"
            ,SUM(CASE WHEN SND_SUCC_YN = 'Y' THEN 1 ELSE 0 END) "발송성공"
            ,SUM(CASE WHEN RCV_CFM_YN = 'Y' THEN 1 ELSE 0 END) "열람확인"
            ,GROUPING_ID(SND.SND_TYP) gid
FROM        POW_BC.TB_BFSCAP_CNSNT_SND_HIST SND
WHERE       1 = 1
AND         SND.SND_YMD BETWEEN (SELECT FM_YMD FROM P) AND (SELECT TO_YMD FROM P)
GROUP BY    ROLLUP(SND.SND_TYP,SND.SND_YMD)
ORDER BY SND.SND_TYP

재귀호촐(Connect By)를 이용한 날짜 더미 데이타셋 생성

간혹 날짜 더미 Inline view가 필요한 경우 다음 SQL로 처리

SELECT  TO_CHAR(CURRENT_DATE -7 + LEVEL,'YYYY-MM-DD')
FROM DUAL
CONNECT BY LEVEL

음. 그런가?

* 욕망을 채우려 하기보다 줄임으로써 행복을 추구하라.

* 21세기의 문맹자는 글을 읽을 줄 모르는 자가 아니라, 배우지 않으며, 배운 것을 버리지 않으며, 다시 배우지 않는 사람이다.

* 한국의 학생들은 하루 15시간을 학교와 학원에서 미래에 필요하지 않은 지식과 존재하지도 않을 직업을 위해 시간을 낭비하고 있다.

- 앨빈토플러 -

임시테이블(GLOBAL TEMPORARY TABLE)

임시 테이블을 구성해서 처리해야되는 경우 힘빼지 말고 이렇게 하지!~

CREATE GLOBAL TEMPORARY TABLE [ON COMMIT DELETE ROWS | ON COMMIT PRESERVE ROWS]
AS
SELECT 1 AS COL1, 'A' AS COL2 FROM DUAL
/

[OPTION]
* ON COMMIT DELETE ROWS : when user exeucte commit process, temporay data is deleted.
* ON COMMIT PRESERVE ROWS : when user disconnect session, temporary data is deleted.

오라클에서의 조인결과 업데이트(BYPASS_UJVC 힌트)

가끔 데이타 업데이트 시 조인결과 셋에 대하여 특정 테이블을 업데이트 해야되는 경우 힘빼지 말고 아래와 같이 하자!~

ps. 단 배치작업에서나 해야지 온라인 처리 시 사용하면 테이블 락 걸릴수 있음.

UPDATE /*+ BYPASS_UJVC */ (
SELECT A.주민번호 주민번호A,B.주민번호 주민번호B
  FROM TABLE_1 A,TABLE_2 B
WHERE A.사원번호=B.사원번호)
   SET 주민번호A=주민번호B
;

SYS_CONNECT_BY_PATH


Row의 데이타를 한 컬럼으로 표현해야되는 경우 아래 함수 적용.

Purpose

SYS_CONNECT_BY_PATH is valid only in hierarchical queries. It returns the path of a column value from root to node, with column values separated by char for each row returned by CONNECT BY condition.

Both column and char can be any of the datatypes CHAR, VARCHAR2, NCHAR, or NVARCHAR2. The string returned is of VARCHAR2 datatype and is in the same character set as column.

Examples

The following example returns the path of employee names from employee Kochhar to all employees of Kochhar (and their employees):

SELECT LPAD(' ', 2*level-1)||SYS_CONNECT_BY_PATH(last_name, '/') "Path"
   FROM employees
   START WITH last_name = 'Kochhar'
   CONNECT BY PRIOR employee_id = manager_id;

Path
---------------------------------------------------------------
 /Kochhar
   /Kochhar/Greenberg
     /Kochhar/Greenberg/Faviet
     /Kochhar/Greenberg/Chen
     /Kochhar/Greenberg/Sciarra
     /Kochhar/Greenberg/Urman
     /Kochhar/Greenberg/Popp
   /Kochhar/Whalen
   /Kochhar/Mavris
   /Kochhar/Baer
   /Kochhar/Higgins
     /Kochhar/Higgins/Gietz

자동차 미션선택 기준

별로 수동이안땡긴다? - 자동추천
수동을 타보고 싶긴하다 - 자동추천
수동을 사려고 생각중인데 옵션이 걸린다 - 자동추천
팔때 저렴해서 구매가 꺼려진다 - 자동추천
교외로 나갈때는 안심인데 도심권에선 복잡하니 잘 안타게 될거같다 - 자동추천
수동이 연비가 장난아니게 좋다던데? - 자동추천
수동을 사야겠다 - 수동추천

ps. ㅋㅋ 참고로 난 수동~


어떻게 애한테 이런 옷을...(19금 판다 ;;)


모든 체위가 이 않에...ㄷㄷ;;

동심파괴 판다.;;

방화벽 환경에서의 고정포트 RMI 통신 처리

RMI Server 생성 시 내부적으로는 포트가 2개 열림(하나는 레지스트리 포트, 다른 하나는 실제 데이타 포트)



레지스트리 포트의 경우 서버 설정 시 고정이나 데이타포트의 경우 임의로 열림. (FTP의 Active모드랑 같은 개념인듯)



방화벽문제로 FTP 서버 구현시에도 passive 모드로 포트 고정하여 구현하듯 RMI 서버 설정 시에도 레지스트리 포트, 데이타 포트 고정해야



방화벽 해제 하여 사용이 가능. (아래 샘플의 경우 레지스트리 포트는 8000, 데이타포트는 8001로 설정)



1. RMI 인터페이스 작성

import java.rmi.*;



public interface BatchController extends Remote {
    void executeBatch(String id, String[] args) throws RemoteException;
    String getBatchLog(String id, int seqNo) throws RemoteException;

}



2. RMI 인터페이스 Implemetation 구현

import java.rmi.*;


public class BatchControllerImpl extends UnicastRemoteObject implements BatchController {
    public BatchControllerImpl(int port) throws RemoteException {
        super(port);
    }



    @Override
    public void executeBatch(final String batchId, final String[] args) throws RemoteException {

        // 배치프로그램 재실행

    }



    @Override

    public String getBatchLog(String id, int seqNo) throws RemoteException {

        // 배치로그내용전송

    }

}





3. RMI listening thread 생성

import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;


public class ProgramMain {

public static void main(String[] args) throws Exception {

Thread rmiTread = new Thread(new Runnable() {
    public void run() {
        try {
            Registry registry = LocateRegistry.createRegistry(8000);
            registry.rebind("BatchController", new BatchControllerImpl(8001));
        }catch(Exception e){
            e.printStackTrace(System.err);
            System.exit(-1);
        }
});
rmiTread.start();

}

}

JAVA에서 SQLite에 사용자정의함수 임베디드하는 법

SQLite 데이타베이스를 사용하는 환경에서 java로 작성된 Function을 프로그램에 임베디드 하여 사용하는 법

▮ 사용할 함수클래스를 작성

import org.sqlite.Function;

public class UserDefinedFunction extends Function  {
    @Override
    protected void xFunc() throws SQLException {
        long param1 = this.value_long(0);
        long param2 = this.value_long(1);
        result(param1 + param2);
    }
}

▮ 작성된 함수클래스를 임베디드

Function.create(connection, "UserDefinedFunction", new UserDefinedFunction());

Implementation of Hash partiton in postgresql

PostgreSQL의 경우 따로 테이블 파티셔닝 기능은 없음.

대용량 데이타베이스를 핸들링 해야되는 경우 아래와 같이 trigger를 이용한 파티셔닝이 가능.

ps. 프로젝트 초반부에는 오픈소스 데이타베이스인 PostgreSQL에서 과연 대용량 처리가 가능할까 의심이 들었는데 결과는 아주 만족스럽. Mysql에 비해 상당히 안정적으로 돌아감.

 1. 파티셔닝키에 사용될 Hash 함수를 생성

create or replace function hash_cust_idfy_id(cust_idfy_id text)
returns int
as
$$ select ascii(substring($1,length($1)))%4 $$
language sql immutable strict;

2. 파티셔닝 테이블 생성

CREATE TABLE tablename (cust_idfy_id text, mdate date);
CREATE TABLE tablename_partition_0 ( CHECK ( hash_cust_idfy_id(cust_idfy_id) = 0 ) ) INHERITS (tablename);
CREATE TABLE tablename_partition_1 ( CHECK ( hash_cust_idfy_id(cust_idfy_id) = 1 ) ) INHERITS (tablename);
CREATE TABLE tablename_partition_2 ( CHECK ( hash_cust_idfy_id(cust_idfy_id) = 2 ) ) INHERITS (tablename);
CREATE TABLE tablename_partition_3 ( CHECK ( hash_cust_idfy_id(cust_idfy_id) = 3 ) ) INHERITS (tablename);

3. 테스트 및 Explain Plan
explain
select * from tablename where cust_idfy_id = '1111' and hash_cust_idfy_id(cust_idfy_id) = hash_cust_idfy_id('1111')

Result  (cost=0.00..40.75 rows=2 width=36)
  ->  Append  (cost=0.00..40.75 rows=2 width=36)
        ->  Seq Scan on tablename  (cost=0.00..0.00 rows=1 width=36)
              Filter: ((cust_idfy_id = '1111'::text) AND ((ascii("substring"(cust_idfy_id, length(cust_idfy_id))) % 4) = 1))
        ->  Seq Scan on tablename_partition_1 tablename  (cost=0.00..40.75 rows=1 width=36)
              Filter: ((cust_idfy_id = '1111'::text) AND ((ascii("substring"(cust_idfy_id, length(cust_idfy_id))) % 4) = 1))



Quartz 라이브러리를 이용한 스케줄링

▮ spring-framework의 어플리케이션 설정파일에 아래 설정 추가

<bean id=jobDetailBean class="org.springframework.scheduling.quartz.JobDetailBean">
    <property name=jobClass value="net.oopscode.ScheduleJobBean"></property>
</bean>

<bean id=cronTriggerBean class="org.springframework.scheduling.quartz.CronTriggerBean">
    <property name=jobDetail ref=jobDetailBean/>
    <property name=cronExpression value="0/10 * * * * ?"/>
</bean>

<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
    <property name="triggers">
       <list>
          <ref bean="cronTriggerBean"/>
       </list>
    </property>
</bean>

▮ 스케줄링할 클래스 생성
public class ScheduleJobBean extends QuartzJobBean {
    @Override
    protected void executeInternal(JobExecutionContext arg0) throws JobExecutionException {
        System.out.println(System.currentTimeMillis());
    }
}

어플리케이션 종료 시 처리방법(Gracefully shutting down)

어플리케이션 종료 직전에 처리해야 할 로직이 있다면



(예를 들어 어플리케이션 종료 시에 현재 처리중인 프로세스는 종료하고 어플리케이션을 종료해야 한다던가, 사용중이던 리소스를 해제하여야 된다던가 하는 등등..)



다음과 같은 코드를 적용



단, 정상적인 kill 시그널인 경우에만 작동함(강제 kill 인 kill -9 같은 경우 작동하지 않음, 이클립스에서도 강제종료 시 확인할수 없음)



public class ApplicationMain {
    public static void main(String[] args) throws Exception {

        // Hooking kill signal.
        Runtime.getRuntime().addShutdownHook(new Thread() {
            public void run() {
                try {
                    System.out.println("+ shutdown application.");
                }catch(Exception e){
                    e.printStackTrace(System.err);
                }
            }
       });
    }
}

GOF 디자인패턴 심플 정리

Design Pattern in Simple Examples

어떤 수술의 디테일한 과정;


Scriptlet and JSTL variable sharing

1.Access scriptlet variable with JSTL

<%
String myVariable = "Test";
pageContext.setAttribute("myVariable", myVariable);
%>

<c:out value="myVariable"/>
2. Access JSTL variable with scriptlet

<c:set var="myVariable" value="Test"/>

<%
String myVariable = (String)pageContext.getAttribute("myVariable");
out.print(myVariable);
%>

ncat 을 이용한 원격지 프로세스 체크

프로그램 변경없이 간단하게 Nmap을 이용하여 다른 시스템에서 해당 시스템의 프로세스 정보를 체크

그러나 이건 진짜 땜빵이고 설계때 부터 운영 관점에서 고려되어야되지 않을런지...

(현재 이 땜빵을 14개 어플리케이션 서버에 적용 중..;;)

1. 일단 nmap 패키지를 설치하자.

RedHat 계열이라면 요렇게..

# Installing nmap package
yum install nmap


2. 다음은 쉘스크립트
#!/bin/sh
# defines application name
APP_NAME="net.oopscode.ApplicaitionMain"

# status task
function status(){
    echo "+ Application Status"
    pid=$(ps -ef | grep "java" | grep ${APP_NAME} | awk {'print $2'})
    if [ ! -z ${pid} ]; then
        top -b -n 1 -p ${pid}
    fi
    ps -ef | grep "java" | grep ${APP_NAME}
}

# notify task
function notify() {
    pid=$(ps -ef | grep "ncat" | grep "${0} status" | awk {'print $2'})
    if [ ! -z ${pid} ]
    then
        kill ${pid}
    fi
    nohup ncat -l 30001 --sh-exec "${0} status" --keep-open > /dev/null &
}

# Main process
case ${1} in
    status)
        status
        ;;
    notify)
        notify
        ;;
    *)
        echo "Usage: "${0}" [status|notify]"
        ;;
esac


3. 모니터링 프로세스 구동 및 테스트
# 프로세스 상태 출력 테스트
monitor.sh status

# ncat 프로세스 시작
monitor.sh notify

# 테스트
telnet localhost 30000

sudo 패스워드 입력없이 사용하는 법

▮ root로 로그인 후 visudo 실행

visudo


▮ sudo로 모든 명령어 권한 설정
[사용자명] ALL=NOPASSWD: ALL


▮ sudo로 지정된 명령어만 사용가능
[사용자명] ALL=NOPASSWD: [명령어1], [명령어2]

▮ tty 없이도 sudo 명령어를 사용하기 위해선 아래 옵션 주석처리 
#Defaults    requiretty

#Defaults   !visiblepw

사직서에 좋은 폰트

Creating CRC32 Hex string

public String getCRC32HexaString(String paramString) throws Exception  {   byte bytes[] = paramString.getBytes(DEFAULT_CHARSET);   Che...