자기 컴에서 /root/.ssh 폴더로 이동
이미 공개키(id_rsa.pub)가 생성되어 있다면 1번 과정 생략하면 된다.

1. 키 생성
[root@mycom~]# ssh-keygen -t rsa

이것저것 세번 물어보는데 세 번 모두 그냥 엔터 !
그러면,
/root/.ssh/id_rsa 에 공개키(id_rsa.pub)와 비밀키(id_rsa)가 생성됨.

2. 키 복사
자기 컴의 공개키를 열어서 내용을 복사한다.
대상 컴퓨터로 접속해서,
/root/.ssh 폴더로 간다 ~
authorized_keys 파일이 없을 경우 만들어서
내용을 붙여넣기 해준다.
있을 경우는 밑에 추가해서 붙여넣어주면 된다~

http://주소.tistory.com/login?requestURI=http://주소.tistory.com/&goDaum=false&loginid=이메일&password=비밀번호&save=on
1. Installing CruiseControl on CentOS with Plesk
http://www.lejnieks.com/2008/07/05/installing-cruisecontrol-on-centos-with-plesk/
CentOs 에서의 CruiseControl 설치법이 있는 사이트


2. Configuration Reference
http://cruisecontrol.sourceforge.net/main/configxml.html
config.xml 레퍼런스가 나와있는 사이트

3. Apache Ant User Manual
http://ant.apache.org/manual/toc.html
Ant 레퍼런스가 나와있는 사이트

Ant 에 대해서 모르고 인터넷에 있는 예제를 따라서 CruiseControl을 만드니, 나와 설정이 너무 달랐다.
Ant 를 먼저 공부하고 맘에 드는 놈을 자신의 환경에 쓰도록 하자.

4. Refactor your configuration file

http://www.build-doctor.com/2008/02/29/refactor-your-configuration-file/
설정파일(config.xml) 리팩토링 !!!
내 config.xml 에는 프로젝트가 몇십개가 된다.
혹시 로그폴더 위치가 바뀌게 된다면??? 몇십개의 줄을 하나마다 바꾸어 줘야한다.
이럴때 ${log.dir} 이라는 property name을 쓴다면 한줄만 바꾸어 주면 된다.
이러한 변수를 잘 활용하고, 또한 프로젝트
<include.project> 를 활용해서 쪼개어 주자.
#define MAX_MESSAGE_NUMBER  100
#define MAX_MESSAGE_SIZE    128
#define MAX_PROCESS_NAME    32

#include <boost/interprocess/ipc/message_queue.hpp>
#include <boost/interprocess/creation_tags.hpp>
#include <iostream>
using namespace boost::interprocess;

class CMessageQ
{

public:
  CMessageQ(const char* pName)
  {
    m_pMsgQ = NULL;
    strcpy(m_Name, pName);
  }
  ~CMessageQ(void)
  {
	  Remove();
  }

public:
  bool Create()
  {
	  try{
			Remove();
			// 메모리에서 제거되면 안되므로 static으로 선언
			static message_queue mq(create_only, m_Name, MAX_MESSAGE_NUMBER, MAX_MESSAGE_SIZE);
			m_pMsgQ = &mq;
	  }catch(interprocess_exception &ex){
		  std::cout << "MessageQ Create() error : " << ex.what() << std::endl;
		  return false;
	  }
	  return true;
  }

  bool Open()
  {
	  try{
		  static message_queue mq(open_only, m_Name);
      m_pMsgQ = &mq;
	  }catch(interprocess_exception &ex){
		  std::cout << "MessageQ Open() error : " << ex.what() << std::endl;
		  return false;
	  }
	  return true;
  }

  size_t Get()
  { 
    size_t temp;
    try{
    temp = m_pMsgQ->get_num_msg();
    return temp;
    }catch(interprocess_exception &ex){
      std::cout << "MessageQ Get() error : " << ex.what() << std::endl;
    }
    return 0;
  }

  template <typename T>
  bool Send(T* Data,size_t Size, unsigned int priority = 0)
  {
	  try{
		  m_pMsgQ->send(Data, Size, priority);
	  }catch(interprocess_exception &ex){
		  std::cout << "MessageQ Send() error : " << ex.what() << std::endl;
		  return false;
	  }
	  return true;
  }

  template <typename T>
  bool Recv(T* Data, size_t Size, unsigned int& priority)
  {
    size_t recvd_size=0;
	  try{
			//m_pMsgQ->receive(Data, Size, recvd_size, priority);
			m_pMsgQ->receive(Data, MAX_MESSAGE_SIZE, recvd_size, priority);
			if( Size != recvd_size )
			{
				std::cout << "MessageQ Recv() Size Wrong : " << std::endl;
				return false;
			}
	  }catch(interprocess_exception &ex){
		  std::cout << "MessageQ Recv() error : " << ex.what() << std::endl;
		  return false;
	  }
	  return true;
  }

  void Remove()
  {
	  message_queue::remove(m_Name);
  }

private:
	char m_Name[MAX_PROCESS_NAME]; // 프로세스 이름
	message_queue* m_pMsgQ; // 메시지큐 포인터
};


이렇게 사용하면 될려나 ㅡㅡ; ㅎㅎ
받는 곳 : http://jira.public.thoughtworks.org/browse/CC

운영체제는 CentOs5.3
최신판인 cruisecontrol-bin-2.8.3 을 받았고, /cruisecontrol-bin-2.8.3 폴더에 압축을 풀었다.
ln -s /cruisecontrol-bin-2.8.3 /cruisecontrol 을 해서 바로 가기를 지정하였다.( 추후 버전 업그레이드시 쉽게 하기위해서)

압축을 풀고 내용을 보면
config.xml (프로젝트 를 여기서 추가)
cruisecontrol.sh (실행파일)
projects폴더 (프로젝트 폴더)
이외 여러가지 파일과 폴더들이 있다.

먼저, cruisecontrol.sh 을 편집해서 java 경로를 지정해 주어야 한다.
맨 아래에
EXE-"$JAVA_HOME/bin/java ~~~~
#JAVA_HOME/bin/java $CC_OPTS ~~~~
이렇게 되어있는데. 자신의 컴에 $JAVA_HOME 가 올바른 java경로로 설정이 되어있어야 실행이된다.

설정이 되어 있지 않다면,
vi ~/.bash_profile 해서
export JAVA_HOME="usr/java/jre1.6.0_13"
export JVAVA_HOME
를 추가 해주자. "" 안은 자신의 자바 경로 !
source ~/.bash_profile을 해서 적용 !

/cruisecontrol 폴더로 이동후
./cruisecontrol.sh & 을 해서 실행해보자. (&는 백그라운드 명렁어)

다음 웹브라우저를 실행하고
http://localhost:8080/dashboard 로 접속을 해보자.

CruiseControl의 Dashboard가 뜰것이다 !!

이상 설치 끝... (생각외로 설치는 간단함)
void Swap(int* a, int* b)
{
int temp;
temp=*a;
*a=*b;
*b=temp;
}

이것이 내가 늘상 쓰던 swap방법이다.
임시 저장 변수가 꼭 필요하다.

void Swap(int* a, int* b)
{
*a = *a + *b;
*b = *a - *b;
*a = *a - *b;
}

원래 있던 두값을 더해서 한 값을 빼주면 나머지 한값이 나오는것을 이용해서,
임시 저장 변수가 필요없는 swap이다.
단점이라면, 당연히 숫자만 된다는 점이다.

원문 :
http://www.boost.org/doc/libs/1_40_0/doc/html/interprocess/synchronization_mechanisms.html#interprocess.synchronization_mechanisms.message_queue


메시지큐란 무엇인가?

메시지큐는 메시지들의 목록과 유사하다. 스레드들은 메시지들을 큐에 넣을 수 있고 큐로 부터 제거할 수도 있다. 각각의 메시지들은 또한 우선순위가 낮은 메시지들보다 먼저 수행될 수 있는 높은 우선순위와 같은 우선순위를 가진다. 각각의 메시지들은 몇가지의 특성을 가지고 있다.

  • 우선순위
  • 메시지의 길이
  • 데이터 (길이가 0보다 크다면)

스레드는 아래의 3가지 방법을 통해 메시지를 보내거나 받을 수 있다.

  • Blocking : 만약 송신시에 메시지큐가 가득찼다거나 수신시에 비었다면, 스레드는 새로운 메시지를 위한 공간이나 날때까지 또는 새로운 메시지가 생길때까지 멈춰(Blocked) 있을 것이다.
  • Try : 만약 송신시에 메시지큐가 가득찼다거나 수신시에 비었다면, 스레드는 그 즉시 에러를 리턴한다.
  • Timed : 만약 송신시에 메시지큐가 가득찼다거나 수신시에 비었다면, 스레드는 성공신호(성공적인 상태를 리턴) 혹은 중단신호(실패를 리턴)가 도착할때까지 행동을 재시도 한다.

메시지큐는 단지 프로세스들 사이에 raw bytes를 복사하고 개체(object)를 전송하지는 않는다. 이것은 만약 우리가 메시지큐를 이용하여 개체(object)를 전송하고 싶다면, 그 개체는 반드시 binary serializable 되어야 한다. 예를 들면, 우리는 프로세스들 사이에 정수(integer)를 전송할 수 있지만 std::string은 전송 할 수 없다. 이때는 Boost.Serialization 또는 Boost.Interprocess 라는 향상된 메커니즘을 사용해서 프로세스들 사이에 복합적인 데이터(complex data)를 전송해야 한다.

Boost.Interprocess 메시지큐는 프로세스간 통신이라고 불린다. 메시지큐는 이름을 사용해서 만들어지고 파일처럼 이름으로 불러온다. 메시지큐를 생성할 때, 사용자는 반드시 메시지의 최대 사이즈와 메시지큐를 저장할 수 있는 최대 메시지 수를 정의하여야 한다. 이러한 파라미터들은 리소스들을 정의 할 것이다.(한 예로, 공유메모리가 사용되고 있다면, 공유메모리(shared memory)의 크기는 메시지큐에 제공된다)
 

using boost::interprocess;
//Create a message_queue. If the queue
//exists throws an exception
message_queue mq
   (create_only         //생성 전용(only create)
   ,"message_queue"     //이름
   ,100                 //최대 메시지 수(max message number)
   ,100                 //최대 메시지 크기(max message size)
   );
using boost::interprocess;
//Creates or opens a message_queue. If the queue
//does not exist creates it, otherwise opens it.
//Message number and size are ignored if the queue
//is opened
message_queue mq
   (open_or_create      //읽기 또는 생성(open or create)
   ,"message_queue"     //이름(name)
   ,100                 //최대 메시지 수(max message number)
   ,100                 //최대 메시지 크기(max message size)
   );
using boost::interprocess;
//Opens a message_queue. If the queue
//does not exist throws an exception.
message_queue mq
   (open_only           //읽기전용(only open)
   ,"message_queue"     //이름(name)
   );


메시지큐는 정적함수 remove를 호출함으로서 명시적으로 제거된다.
using boost::interprocess;
message_queue::remove("message_queue");

이 함수는 만약 메시지큐가 여전히 다른 프로세스에 의해 사용되고 있을 경우 실패할 수 있다.


메시지큐 사용법

메시지큐를 사용하기 위해서는 다음의 헤더파일을 포함해야 한다.
#include <boost/interprocess/ipc/message_queue.hpp>

아래 예 처럼, 첫번째 프로세스가 메시지큐를 생성하고 거기에다가 정수 배열을 쓴다. 다른 프로세스는 단지 배열을 읽고 순서가 맞는지 확인한다. 이것이 첫번째 프로세스이다.
#include <boost/interprocess/ipc/message_queue.hpp>
#include <iostream>
#include <vector>

using namespace boost::interprocess;

int main ()
{
   try{
      //Erase previous message queue
      message_queue::remove("message_queue");

      //Create a message_queue.
      message_queue mq
         (create_only               //only create
         ,"message_queue"           //name
         ,100                       //max message number
         ,sizeof(int)               //max message size
         );

      //Send 100 numbers
      for(int i = 0; i < 100; ++i){
         mq.send(&i, sizeof(i), 0);
      }
   }
   catch(interprocess_exception &ex){
      std::cout << ex.what() << std::endl;
      return 1;
   }

   return 0;
}



이것이 두번째 프로세스이다.
#include <boost/interprocess/ipc/message_queue.hpp>
#include <iostream>
#include <vector>

using namespace boost::interprocess;

int main ()
{
   try{
      //Open a message queue.
      message_queue mq
         (open_only        //only create
         ,"message_queue"  //name
         );

      unsigned int priority;
      std::size_t recvd_size;

      //Receive 100 numbers
      for(int i = 0; i < 100; ++i){
         int number;
         mq.receive(&number, sizeof(number), recvd_size, priority);
         if(number != i || recvd_size != sizeof(number))
            return 1;
      }
   }
   catch(interprocess_exception &ex){
      message_queue::remove("message_queue");
      std::cout << ex.what() << std::endl;
      return 1;
   }
   message_queue::remove("message_queue");
   return 0;
}


이 클래스와 동작에 대해서 더 알고 싶다면
boost::interprocess::message_queue 클래스 참고를 보기바란다.
과자인줄 알고 받았던 실행파일이 바로 Advanced virus remover 였다.
그럴듯하게 백신 프로그램 형태를 하고 있지만,,, 돈 내라고 소리를 지르는 걸 보면 허위 백신 프로그램이다.
오히려 어떻게 해서든 겁을 주려고 띄우는 메시지를 보면 귀엽다.ㅎ

사용자 삽입 이미지


바탕화면이 파랗게 되고 되도 않은 경고 이미지가 붙어있다.
또한 레지스트리 편집기, 작업관리자, 도스창도 열리지 않는다. (계산기까지 못열리게 하는건 좀 심했다ㅠ)

외국에서 퍼지는 거라서 국내 검색을 찾으니 정보가 거의 없었다.

http://www.xdelbox.com/how-to-remove-advanced-virus-remover-free/

위 사이트를 참고로 해결을 하였다.
설명을 하자면,

1. 오른쪽마우스 새로만들기->텍스트 문서를 연다.

File::
c:\windows\system32\winupdate.exe
c:\windows\system32\winhelper.dll
c:\windows\system32\AVR09.exe
c:\Program Files\AdvancedVirusRemover\PAVRM.exe

 이렇게 작성을 하고 cfscript.txt 로 저장을 한다.

2. 위 사이트에 링크되어 있는 ComboFix.exe 를 cfscript.txt와 동일한 경로에 다운로드 받는다.

이때, 저장 이름을 Combo-Fix.exe로 하도록 한다. 왜 그런지는 모르겠으나 하라니 따라해야지 ~

3. txt 문서를 드래그 해서 Combo-Fix.exe 아이콘 위에다가 놓는다.

4. 띡띡소리가 나면서 뭔가를 분석을 할 것이다. 그럼 중간중간 확인을 눌러주면서 기다리면 된다.

돌아가는 것을 보니까 파일 삭제를 하고 윈도우 복구를 시켜주는 듯 했다.

나의 경우는 총 20분쯤 걸린것 같다 ~

과자받을때 조심해야지 ㅠ
트랜잭션(Transaction)은 ATM, 데이터베이스 등의 시스템에서 사용되는 쪼갤 수 없다는 업무처리의 단위이다.

영어의 Transaction은 거래를 뜻한다. 예를 들어 돈을 주었는데 물건을 받지 못한다면, 그 거래는 이루어지지 못하고 원상태로 복구되어야 한다. 이와 같이 쪼갤 수 없는 하나의 처리 행위를 원자적 행위라 고 한다. 여기서 쪼갤 수 없다는 말의 의미는 실제로 쪼갤 수 없다기보다는 만일 쪼개질 경우 시스템에 심각한 오류를 초래할 수 있다는 것이다. 이러한 개념의 기능을 ATM 또는 데이터베이스 등의 시스템에서 제공하는 것이 바로 트랜잭션이다.

트랜잭션은 사용자가 시스템에 요구를 시작하여 시스템 내의 처리, 시스템에서 사용자에게 응답하는 모든 처리를 포함한다. 이러한 트랜잭션이 충족해야 하는 기술적인 요건은 ACID가 있다.

출처 : 위키백과

http://ko.wikipedia.org/wiki/%ED%8A%B8%EB%9E%9C%EC%9E%AD%EC%85%98


1. 트랜잭션(transaction)
하나의 논리적 기능을 수행하기 위한 작업의 단위로서 데이타베이스의 일관된 상태를 또 다른 일관된 상태로 변환시킨다.

2. 트랜잭션 특성 (ACID)
(1). 원자성(Atomicity)
 트랜잭션은 자기의 션산을 전부 또는 전무(all or nothing) 실행만이 있지 일부 실행으로 트랜잭션의 기능을 갖는 것은 아니다.

(2). 일관성(Consistency)
 트랜잭션이 그 실행을 성공적으로 완료하면 언제나 일관성 있는 데이타베이스 상태로 변환한다. 즉, 트랜잭션 실행의 결과로 데이타베이스 상태가 모순되지 않는다.

(3). 격리성(Isolation)
 트랜잭션이 실행 중에 있는 연산의 중간 결과는 다른 트랜잭션이 접근할 수 없다.

(4). 영속성(Durability)
 트랜잭션이 일단 그 실행을 성공적으로 완료하면 그 결과는 영속적이다. 따라서 시스템은 어떤 경우에도 완료된 결과의 영속성을 보장해야 한다.

3. 트랜잭션 예 (계좌 이체)

T : Begin_Trans
       Read(A)
         A=A-100
       Write(A)
       Read(B)
         B=B+100
       Write(B)
     End_Trans

이 트랜잭션이 갖는 일관성 제약은, 이 트랜잭션이 실행되더라도 계좌 A와 계좌 B의 합계는 변하지 않아야 된다는 것이다.
A=A-100을 실행하고 B=B+100을 실행하는 도중 장애가 있어났다면 계좌 A와 계좌 B의 합계는 트랜잭션 T의 실행 전과 달라져 버리게 되어 일관성 제약을 위반하게 된다.
이러한 상태는 모순 상태(inconsistent state)라고 하는데 이러한 모순은 데이타베이스에서 허용되지 않는다.
원자성은 트랜잭션 실행의 시작에서부터 성공적으로 마칠 때까지를 한 단위로 해서 일관성을 검사하는 것이다.
원자성을 위한 연산에는 Commit(완료)와 Rollback(복귀) 연산이 있다.
Commit연산을 수행하면 그 트랜잭션의 실행이 성공적으로 종료되었음을 선언하는 것이다.
따라서 데이타베이스 상태는 일관성 있는 상태로 변환되었고 갱신된 데이타 아이템들의 값은 영속성을 갖도록 시스템이 보장하게 된다.
그러나 트랜잭션이 Rollback 연산을 수행하면 트랜잭션의 실행이 실패했음을 선언하는 것이다. 따라서 이 트랜잭션이 수행한 연산의 결과는 원상 복귀시켜야 된다.

4. 트랜잭션 상태
(1) 활동(active)
 트랜잭션이 Begin_Trans에서부터 실행을 시작하였거나 실행 중인 상태
(2) 부분완료(partially committed)
 트랜잭션이 마지막 명령문을 실행한 직후의 상태
(3) 실패(failed)
 정상적 실행을 더 이상 계속할 수 없어서 중단한 상태
(4) 완료(commited)
 트랜잭션이 실행을 성공적으로 완료하여 Commit 연산을 수행한 상태

BEGIN_TRANS;
       UPDATE
ACCOUNT
       SET Balace = Balance-100
       WHERE Accnt = 'A';
       IF ERROR GO TO UNDO;

       UPDATE
ACCOUNT
       SET Balace = Balance+100
       WHERE Accnt = 'B';
       IF ERROR GO TO UNDO;

       COMMIT
TRANS;
       GO TO
FINISH;

    UNDO:
       ROLLBACK
TRANS;
    FINISH:
       RETURN;

END_TRANS;

참고 & 출처 : 데이타베이스 시스템(DATABASE SYSTEM). 정익사. 이석호 저
C언어에서 포인터를 이해하는 것은 생각만큼 쉽지 않다.
포인터를 이해하지 않고 사용할 경우 생기는 위험성이 크고,
팀 작업의 경우 자신의 잘못된 포인터 사용으로 온종일 디버깅해야 하는 경우도 생길 수 있다.
포인터를 이용해서 참조 호출을 할 경우 원래의 값이 바뀌기 때문이다.

하지만 간단한 포인터 예제를 통해서 이해만 한다면 거부감이 조금은 사라질 것이다.

int age;
여기서 age는 변수명이고, int는 자료형이다.
32bit 에서 int는 4바이트이므로,
메모리상에서 어떤 4바이트 공간을 작업자는 age라고 부른다.
age = 26;
을 하게 되면 그 4바이트 공간에 26이라는 값이 들어가게 되고,
결국 age는 26이라는 값을 갖게 되는것이다.

int* p_age;
p_age라는 변수는 int* 라는 자료형이다.
*는 포인터, 즉 '가리키는'이라고 이해하면 쉬울 것 같다.
말을 풀어쓰면,
p_age는 메모리상의 int 자료형을 가리키는 변수이다.

그래서 p_age변수는 int형을 자료형을 가진 다른 변수의 주소값을 자신의 값으로 가진다.
p_age = &age;

age라는 변수의 메모리상 주소가 0xA 라고 했을때,
p_age는 0xA 라는 값을 가지게 된다.

*p_age = 30;
p_age의 값 (0xA) 가 가리키는 변수(age) 의 값을 30으로 쓴다.


void dGet_value2(void* *p2)
{
  printf("&p2:0x%04x\n", &p2);
  printf("p2:0x%04x\n", p2);
  printf("*p2:0x%04x\n", *p2);
  printf("\n");

  static int value = 5;
  *p2 = &value;
}

void dGet_value1(int* *p1)
{
  printf("&p1:0x%04x\n", &p1);
  printf("p1:0x%04x\n", p1);
  printf("*p1:0x%04x\n", *p1);
  printf("\n");

  dGet_value2((void **)&(*p1));
}
int _tmain(int argc, _TCHAR* argv[])
{
  int* pmain;
  printf("&pmain:0x%04x\n", &pmain);
  printf("pmain:0x%04x\n", pmain);
  printf("\n");

  dGet_value1(&pmain);

  printf("pmain-> %d\n",*pmain);
	return 0;
}

+ Recent posts