Distributed System-remote procedure call

What's local procedure call?
A program invoke a local procedure call, pass it parameters and get the return data. See example:
ret_type func(para_type arg);
int main(int argc, char* argv[]){
...
ret_type ret=func((para_type)xxx);
...
}

What's remote procedure call?
In an client/server system, an client could run an procedure on server machine by sending request and attendant parameters to server, and get the result returned from procedure operating result.

Posted in old things | Leave a comment

重写operator new&delete

重写new关键字需要注意:
void * operator new(size_t size);
1> c++标准要求,即使在请求分配0字节内存时,operator new也要返回一个合法指针。比如分配一个1字节大小的内存。
2> operator new内部包含一个无限循环,跳出循环的唯一办法是内存分配成功或出错处理函数完成了条款7所描述的事件中的一种:得到了更多的可用内存、安装了一个新的new-handler(出错处理函数)、卸除了mem_out_handler、抛出了一个std::bad_alloc或其派生类型的异常、或者返回失败。
3> operator new经常会被子类继承,由于存在继承,基类中的operator new可能会被调用去为一个子类对象分配内存。从new函数的原型---------可知,调用父类的new函数时,传入的size比父类的sizeof大,因此简单的做法是分配此“错误”的size内存(: :o perator new(size))。

重写delete函数需要注意:
void operator delete(void *rawmemory, size_t size);
1> C++标准要求,允许rawmemory为空指针。
2> 子类继承时,delete子类时,基类中的operator delete传入的size参数可能和父类的sizeof不一致,此时也应该delete子类的内存空间(: :o perator delete(size))。

Posted in C++技术 | Leave a comment

处理new操作内存不足

*********************************************************************************
简单的方法
类定义
typedef void (*mem_out_handler)();

class x {
public:
static mem_out_handler set_handler(mem_out_handler p);
static void * operator new(size_t size);

private:
static mem_out_handler currenthandler;
};

mem_out_handler x::set_handler(mem_out_handler p)
{
mem_out_handler oldhandler = currenthandler;
currenthandler = p;
return oldhandler;
}
void * x: :o perator new(size_t size)
{
mem_out_handler globalhandler = std::set_new_handler(currenthandler);// 安装x的new_handler
void *memory;
try { // 尝试分配内存
memory = : :o perator new(size);
}
catch (std::bad_alloc& ;) { // 恢复旧的new_handler
std::set_new_handler(globalhandler);
throw; // 抛出异常
}
std::set_new_handler(globalhandler); // 恢复旧的new_handler
return memory;
}
mem_out_handler x:currenthandler=NULL;

内存分配
static void nomorememory();// x的对象分配内存失败时调用的new_handler函数的声明

x::set_handler(nomorememory);// 把nomorememory设置为x的mem_out_handler函数
x *px1 = new x; // 如内存分配失败,调用nomorememory
x::set_handler(0); // 设x的mem_out_handler函数为空
x *px2 = new x; // 如内存分配失败,立即抛出异常。(类x当前没有mem_out_handler函数)

*********************************************************************************
可重用方法

定义
template
class base {
public:
static mem_out_handler set_handler(mem_out_handler p);
static void * operator new(size_t size);

private:
static mem_out_handler currenthandler;
};

template
mem_out_handler base::set_handler(mem_out_handler p)
{
mem_out_handler oldhandler = currenthandler;
currenthandler = p;
return oldhandler;
}

template
void * newhandlersupport: :o perator new(size_t size)
{
mem_out_handler globalhandler =
std::set_new_handler(currenthandler);
void *memory;
try {
memory = : :o perator new(size);
}
catch (std::bad_alloc& ;) {
std::set_new_handler(globalhandler);
throw;
}

std::set_new_handler(globalhandler);
return memory;
}

template
mem_out_handler base::currenthandler=NULL;

//inheritance from mixin base class template.
class x: public base {
... // as before, but no declarations for set_handler or operator new
};

Posted in C++技术 | Leave a comment

how to redirect output of an running process

http://etbe.coker.com.au/2008/02/27/redirecting-output-from-a-running-process/

Note: redirecting output of an running process, not when starting a process, so '>' is ignored.
Take cat > /home/fist/output for example, this command would accept input of prompt, and write user inputs to the file "/home/fist/output".
What should we do , if we want to redirect the output of the program to another file, /home/fist/direct.txt for instance?
With the help of gdb, we can attach a running process, manipulating it's resources, passing messages, and invoking system calls in its' context.
As we know, there are three standard file: stdin, stdout and stderr, which are indexed by 0, 1 and 2 in a processes' context(0, 1, 2.etc are file descriptor). When we open a new file right after closing an existing one, the new file's descriptor would be just the same as the previous one. So, if we close stdout, and creat another one, the later one would use the file descriptor "1".
But how to close an existing file, and open another one? Follow me!
..............................................................................................
$ pgrep watch
3457
$ which watch
/usr/bin/watch
$ gdb -p 3457 /usr/bin/watch
...
(gdb) p close(1)
$1 = 0
(gdb) p creat("/home/fist/redirect", 0644)
$2 = 1
(gdb) quit
The program is running. Quit anyway(and detach it)?(y or n) y
Detaching from program: /usr/bin/watch, process 3457
..............................................................................................
The “p” command in GDB will print the value of an expression, an expression can be a function to call, it can be a system call… So I execute a close() system call and pass file handle 1, then I execute a creat() system call to open a new file. The result of the creat() was 1 which means that it replaced the previous file handle. If I wanted to use the same file for stdout and stderr or if I wanted to replace a file handle with some other number then I would need to call the dup2() system call to achieve that result.
To verify the result, we type some words into the session of cat, and see the content of /home/fist/redirect.You will see the difference.
Also, if you want to close the original session you need to close all file handles for it, open a new device that can be the controlling tty, and then call setsid().
..............................................................................................
[More]
Above method can be used to debug a running program ,by redirecting stdin, stdout and stderr to another session.The program can be a dameon, a program with no GUI interface, a console, etc.
Another advanced debugging method is signal. When programing, debug is planted in the program's gene.By sending,capturing and handling signal, more complicated debugging methods are supported.

Posted in old things | Leave a comment

Architecture of MessagePack

OverView

MessagePack offers two layered software components.
1.MessagePack is an efficient object serialization library.It enables to exchange structured objects between many languages like JSON. But unlike JSON, it is very fast and small.
2.MessagePack-RPC is the remote procedure call system on top of the MessagePack serialization library.It is a cross-language RPC library for client, server and cluster applications, which releases you from complicated network programming completely and provides well-designed API.
Posted in 进程通信 | Leave a comment

Paxos算法

http://zh.wikipedia.org/wiki/Paxos%E7%AE%97%E6%B3%95

http://en.wikipedia.org/wiki/Paxos_(computer_science)

Paxos 算法解决的问题是一个分布式系统如 何就某个值(决议)达成一致。一个典型的场景是,在一个分布式数据库系统中,如果各节点的初始状态一致,每个节点都执行相同的操作序列,那么他们最后能得 到一个一致的状态。为保证每个节点执行相同的命令序列,需要在每一条指令上执行一个“一致性算法”以保证每个节点看到的指令一致。这在节点可能无法连接的情况下变得更加困难。一个通用的一致性算法可 以应用在许多场景中,是分布式计算中的重要问题。因此从20世纪80年代起对于一致性算法的研究就没有停止过。节点通信存在两种模型:共享内存(Shared memory)和消息传递(Messages passing)。Paxos 算法就是一种基于消息传递模型的一致性算法。

场景定义:

将节点的角色分为 proposers,acceptors,和 learners(允许身兼数职)。proposers 提出决议,acceptors 批准决议,learners“学习”决议。

需求定义:

  1. 决议(value)只有在被 proposers 提出后才能批准(未经批准的决议称为“提案(proposal)”);
  2. 在一次 Paxos 算法的执行实例中,只批准一个 Value;
  3. learners 只能获得被批准(chosen)的 Value。

算法的内容:

proposer 提出一个提案前,首先要和足以形成多数派的 acceptors 进行通信,获得他们进行的最近一次批准活动的编号(prepare 过程),之后根据回收的信息决定这次提案的 value,形成提案开始投票。当获得多数 acceptors 批准后,提案获得通过,由 proposer 将这个消息告知 learner。这个简略的过程经过进一步细化后就形成了 Paxos 算法。

决议的提出与通过:

通过一个决议分为两个阶段:

  1. prepare 阶段:
    1. proposer 选择一个提案编号 n 并将 prepare 请求发送给 acceptors 中的一个多数派;
    2. acceptor 收到 prepare 消息后,如果提案的编号大于它已经回复的所有 prepare 消息,则 acceptor 将自己上次的批准回复给 proposer,并承诺不再批准小于 n 的提案;
  2. 批准阶段:
    1. 当一个 proposor 收到了多数 acceptors 对 prepare 的回复后,就进入批准阶段。它要向回复 prepare 请求的 acceptors 发送 accept 请求,包括编号 n 和根据 P2c 决定的 value(如果根据 P2c 没有决定 value,那么它可以自由决定 value)。
    2. 在不违背自己向其他 proposer 的承诺的前提下,acceptor 收到 accept 请求后即批准这个请求。

决议的发布:

一个显而易见的方法是当 acceptors 批准一个 value 时,将这个消息发送给所有 learner。但是这个方法会导致消息量过大。
由于假设没有 Byzantine failures,learners 可以通过别的 learners 获取已经通过的决议。因此 acceptors 只需将批准的消息发送给指定的某一个 learner,其他 learners 向它询问已经通过的决议。这个方法降低了消息量,但是指定 learner 失效将引起系统失效。
因此 acceptors 需要将 accept 消息发送给 learners 的一个子集,然后由这些 learners 去通知所有 learners。
但是由于消息传递的不确定性,可能会没有任何 learner 获得了决议批准的消息。当 learners 需要了解决议通过情况时,可以让一个 proposer 重新进行一次提案。注意一个 learner 可能兼任 proposer。

Progress 的保证:

根据上述过程当一个 proposer 发现存在编号更大的提案时将终止提案。这意味这提出一个编号更大的提案会终止之前的提案过程。如果两个 proposer 在这种情况下都转而提出一个编号更大的提案,就可能陷入活锁,违背了 Progress 的要求。这种情况下的解决方案是选举出一个 president,仅允许 president 提出提案。但是由于消息传递的不确定性,可能有多个 proposer 自认为自己已经成为 president。Lamport 在The Part-Time Parliament一文中描述并解决了这个问题。

Posted in 算法 | Leave a comment

qt事件处理和事件过滤

1.事件驱动模式

在事件驱动的程序中,GUI视图需要响应object的状态变化,作出特定反应。当状态变化时,将对应的信息发送给接收者。
事件的来源有两类,一种是系统事件,例如鼠标键盘事件,qt获取到这些来自系统底层的消息,将它们转换成qt的事件,放入事件队列;另一种是应用程序事件,例如postEvent/sendEvent。
事件通过各种各样的方式在object间传递。QWidget通过QEvent发送给其他QObject,以相应鼠标或键盘操作;QObject之间可通过signal/slot机制进行事件处理。

2.事件处理流程

3.event loop

下面是一个典型的qt主程序示例:
int main(int argc, char * argv[]) {
QApplication myapp(argc, argv); 1
QWidget
rootWidget;
setGui(&rootWidget);
rootWidget.show(); 2
return myapp.exec(); 3
};

1 Every GUI, multithreaded, or event-driven Qt Application must have a QApplication object defined at the top of main().
2 Show the widget on the screen.
3 Enter an event loop.

当调用QApplication::exec()函数之后,程序就进入了event loop,接收、处理、分发各种事件,直到程序退出。QApplication::exec()的简化逻辑如下所示:
while ( !app_exit_loop ) {
while( !postedEvents ) {             processPostedEvents()       }
while( !qwsEvnts ){            qwsProcessEvents();   }
while( !postedEvents ) {             processPostedEvents()       }
}

4.事件处理和事件过滤方法

1)QEvent子类
qt4.*中继承自QEvent的子类有QTimerEvent, QMouseEvent, QWheelEvent, QTabletEvent, QKeyEvent, QFocusEvent, QPaintEvent, QMoveEvent, QResizeEvent, QCloseEvent, QIconDragEvent, QShowEvent, QHideEvent, QContextMenuEvent, QIMEvent, QDropEvent, QDragLeaveEvent, QChildEvent, QCustomEvent.
开发者可以通过重载QWidget和QObject提供的事件处理方法,来响应对应的事件。例如,重载QWidget::mousePressEvent ( QMouseEvent * e )之后,我们就可以自行处理窗体的鼠标点击事件。

2)QObject::event()
通过重载event(),可以在某些事件到达本实例的特定事件处理器之前处理他们。对于那些没有明确需要预先处理的事件,需要调用其基类的event()函数。

3)QObject event filter
QObject::installEventFilter ( const QObject * filterObj )方法将filterObj注册为本对象的事件监视对象,即所有本对象的事件都会发送到filterObj。filterObj在QObject::eventFilter(QObject *o, QEvent *e )方法中截获并过滤所有事件,重载此方法,在其中过滤特定的事件。在对特定事件进行过滤之后,eventFilter需要返回TRUE,若不需要过滤或者要将过滤后的事件继续传递下去,则返回FALSE,此时要保证不要delete掉事件e。
一个监视器可以监视多个QObject,一个QObject可以被多个监视器监视,如果QObject被多个监视器监视,则消息按照监视器被注册的顺序传递到各个监视器。

4)QApplication::notify()
Qt调用QApplication::notify( QObject * receiver, QEvent * e )方法将事件e发送到receiver。

5)注册QApplication的监视器
所有事件在被处理和过滤之前,将被此监视器过滤。

Posted in C++技术 | Leave a comment

C++前置声明

C++前置声明

1.定义

什么是C++的前置声明?

首先,参考下列两个类的定义:

//a.h

#include "b.h"

class A {

...

B   m_b;

};

//b.h

#include "a.h"

class  B{

...

A m_a;

};

这就出现了类的先后定义问题,到底编译器是先编译class A,还是class B。解决方法便是前置声明。如下所示:

//a.h

#include "b.h"

class B;

class A {

...

B   m_B;

};

//b.h

#include "a.h"

class  B{

...

A m_A;

};

2.高级

前置声明的最初用途就是用来解决上述的依赖问题,但是展示出了更高级的特性。

从类的构造和C++对象存储空间的角度来看,在定义上述class A(即实际分配存储空间时),编译器需要知道class B的声明,以方便为A::m_B分配存储空间,因此需要编译class B。在实际工程中,如果我们修改了b.h,则class B需要重新编译,进而也需要重新编译class A,尽管a.h并没有作修改。

我们自然希望能够在修改b.h之后,不需要重新编译a.h,以减少编译的时间。这可以通过前置声明来减少编译依赖。在class A中,我们将m_B声明为指针或者引用类型,这样,A在编译时,固定为m_B分配sizeof(void*)字节的空间,当class B的声明发生变化时,不会影响class A的定义,因而在重新编译b.h时,就不需要重新编译a.h。

因此,实际工程中,可以通过前置声明配合指针或引用类型声明来减少编译依赖。实例如下:

//a.h

#include "b.h"

class B;

class A{

...

B* m_pB;//B& m_refB;

};

//b.h

#include "a.h"

class A;

class B{

...

A* m_pA;//A& m_refA;

};

Posted in C++技术 | Tagged | Leave a comment

我能如何

21日是她生日,周二,提前几天给她准备生日礼物,算个小惊喜吧。17日,电暖气买来了,送6楼去了,说是公司规定不许用电暖气,晚上自己灰溜溜又搬了回去。18日,发出多条短信,均无应答。19日又是数条短息,亦无应答。呵呵。不给力。20日,回短信,问我是不是发了什么短信给她,希望补过生日。20日晚一夜没睡,在网上订购了一束花,名叫甜蜜圣诞,花朵是金莎巧克力。下午5点收到。没有一句谢谢。晚上11点,告诉我有男朋友了。

over...
Posted in old things | Leave a comment

赠我轻浮

今日周末,借口到海岸城找人办事,邀其回家同行。
5点10分,发QQ信息请求与其共进晚餐。等待。。。
5点30分,仍未回消息,但是状态显示已下线。
果断熄灭刚点燃的一只黄鹤楼,追至楼下大门外,无影,去电,不接。收到短信说领佳节又重阳导要留下吃饭,不能同行。
回厂领取自行车,下班回家。
思量无果,请朋友分析情况,原因可能有二:我太仓促或者她不好意思。
晚9点,去电,无应答。
晚11点,去信息,“我没把你看轻,不要把我看那么轻浮:>”
晚11点半,回信息,“你怎样定义轻浮呢”
晚12点,去信息,“不好说,要说也没机会”
晚12点整,回信息,“零点零零分,好诡异。。。怎么不好说,这么早睡,不像你,明天要加班吧”
晚12点1分,去信息,“are u ready to call me 轻浮 from now on”
晚12点2分,回信息,“我最近和供应商电话沟通太多了,有点沟通厌烦症,领佳节又重阳导吃饭又成了工作动员,安了”
时间是磨练人的最好导师,但是他的学生都被磨练死了。
时间是雕琢人的最好工具,但是大部分都是残次品。
时间是培养感情的温床,但是能抵挡不住激情之潮的退去吗?
时间是考验感情的考题,但是磨练越多、误解与不信任是否会减少呢?
如果你给我这样的磨练,我选择接受,但是现实能否接受。
如果你要雕琢我,请告诉我你的期望,不要让我去胡乱猜测猜答案。
这是我想要的吗,我不知道是不是那个答案,但是已经接近。
爱你,只想了解你
爱你,只想给你快乐
爱你,不要拒绝我,也不求赞同我
愿时间能淘去我的轻浮,赠予你喜。
Posted in old things | Leave a comment