智能指针(move sementic)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
#ifndef SMART_PTR_H
#define SMART_PTR_H

#include <atomic> // std::atomic
#include <utility> // std::swap

class shared_count {
public:
shared_count() noexcept
: count_(1)
{
}
void add_count() noexcept
{
count_.fetch_add(1, std::memory_order_relaxed);
}
long reduce_count() noexcept
{
return --count_;
}
long get_count() const noexcept
{
return count_;
}

private:
std::atomic_long count_;
};

template <typename T>
class smart_ptr {
public:
template <typename U>
friend class smart_ptr;

explicit smart_ptr(T* ptr = nullptr)
: ptr_(ptr)
{
if (ptr) {
shared_count_ = new shared_count();
}
}
~smart_ptr()
{
if (ptr_ && !shared_count_->reduce_count()) {
delete ptr_;
delete shared_count_;
}
}

smart_ptr(const smart_ptr& other) noexcept
{
ptr_ = other.ptr_;
if (ptr_) {
other.shared_count_->add_count();
shared_count_ = other.shared_count_;
}
}
template <typename U>
smart_ptr(const smart_ptr<U>& other) noexcept
{
ptr_ = other.ptr_;
if (ptr_) {
other.shared_count_->add_count();
shared_count_ = other.shared_count_;
}
}
template <typename U>
smart_ptr(smart_ptr<U>&& other) noexcept
{
ptr_ = other.ptr_;
if (ptr_) {
shared_count_ = other.shared_count_;
other.ptr_ = nullptr;
}
}
template <typename U>
smart_ptr(const smart_ptr<U>& other, T* ptr) noexcept
{
ptr_ = ptr;
if (ptr_) {
other.shared_count_->add_count();
shared_count_ = other.shared_count_;
}
}
smart_ptr& operator=(smart_ptr rhs) noexcept
{
rhs.swap(*this);
return *this;
}

T* get() const noexcept
{
return ptr_;
}
long use_count() const noexcept
{
if (ptr_) {
return shared_count_->get_count();
} else {
return 0;
}
}
void swap(smart_ptr& rhs) noexcept
{
using std::swap;
swap(ptr_, rhs.ptr_);
swap(shared_count_, rhs.shared_count_);
}

T& operator*() const noexcept
{
return *ptr_;
}
T* operator->() const noexcept
{
return ptr_;
}
operator bool() const noexcept
{
return ptr_;
}

private:
T* ptr_;
shared_count* shared_count_;
};

template <typename T>
void swap(smart_ptr<T>& lhs, smart_ptr<T>& rhs) noexcept
{
lhs.swap(rhs);
}

template <typename T, typename U>
smart_ptr<T> static_pointer_cast(const smart_ptr<U>& other) noexcept
{
/** static_cast
①用于类层次结构中基类(父类)和派生类(子类)之间指针或引用的转换。
进行上行转换(把派生类的指针或引用转换成基类表示)是安全的;
进行下行转换(把基类指针或引用转换成派生类表示)时,由于没有动态类型检查,所以是不安全的。
②用于基本数据类型之间的转换,如把int转换成char,把int转换成enum。
③把空指针转换成目标类型的空指针。
④把任何类型的表达式转换成void类型。
注意:static_cast不能转换掉expression的const、volatile、或者__unaligned属性
*/
T* ptr = static_cast<T*>(other.get());
return smart_ptr<T>(other, ptr);
}

template <typename T, typename U>
smart_ptr<T> reinterpret_pointer_cast(const smart_ptr<U>& other) noexcept
{
//用于进行各种不同类型的指针之间、不同类型的引用之间以及指针和能容纳
//指针的整数类型之间的转换。转换时,执行的是逐个比特复制的操作。
T* ptr = reinterpret_cast<T*>(other.get());
return smart_ptr<T>(other, ptr);
}

template <typename T, typename U>
smart_ptr<T> const_pointer_cast(const smart_ptr<U>& other) noexcept
{
T* ptr = const_cast<T*>(other.get());
return smart_ptr<T>(other, ptr);
}

template <typename T, typename U>
smart_ptr<T> dynamic_pointer_cast(const smart_ptr<U>& other) noexcept
{
T* ptr = dynamic_cast<T*>(other.get());
return smart_ptr<T>(other, ptr);
}

#endif // SMART_PTR_H

参考资料

  • [现代c++实战30讲]

查看更多

springsnail源码分析

fdwrapper

都是些辅助函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
#ifndef FDWRAPPER_H
#define FDWRAPPER_H

enum RET_CODE { OK = 0, NOTHING = 1, IOERR = -1, CLOSED = -2, BUFFER_FULL = -3, BUFFER_EMPTY = -4, TRY_AGAIN };
enum OP_TYPE { READ = 0, WRITE, ERROR };
int setnonblocking( int fd );
void add_read_fd( int epollfd, int fd );
void add_write_fd( int epollfd, int fd );
void removefd( int epollfd, int fd );
void closefd( int epollfd, int fd );
void modfd( int epollfd, int fd, int ev );

#endif
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#ifndef FDWRAPPER_H
#define FDWRAPPER_H

#include <unistd.h>
#include <fcntl.h>
#include <sys/epoll.h>

int setnonblocking( int fd )
{
int old_option = fcntl( fd, F_GETFL );
int new_option = old_option | O_NONBLOCK;
fcntl( fd, F_SETFL, new_option );
return old_option;
}

void add_read_fd( int epollfd, int fd )
{
epoll_event event;
event.data.fd = fd;
event.events = EPOLLIN | EPOLLET;
epoll_ctl( epollfd, EPOLL_CTL_ADD, fd, &event );
setnonblocking( fd );
}

void add_write_fd( int epollfd, int fd )
{
epoll_event event;
event.data.fd = fd;
event.events = EPOLLOUT | EPOLLET;
epoll_ctl( epollfd, EPOLL_CTL_ADD, fd, &event );
setnonblocking( fd );
}

void closefd( int epollfd, int fd )
{
epoll_ctl( epollfd, EPOLL_CTL_DEL, fd, 0 );
close( fd );
}

void removefd( int epollfd, int fd )
{
epoll_ctl( epollfd, EPOLL_CTL_DEL, fd, 0 );
}

void modfd( int epollfd, int fd, int ev )
{
epoll_event event;
event.data.fd = fd;
event.events = ev | EPOLLET;
epoll_ctl( epollfd, EPOLL_CTL_MOD, fd, &event );
}

#endif

conn

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
#ifndef CONN_H
#define CONN_H

#include <arpa/inet.h>
#include "fdwrapper.h"

class conn
{
public:
conn();
~conn();
void init_clt( int sockfd, const sockaddr_in& client_addr );
void init_srv( int sockfd, const sockaddr_in& server_addr );
void reset();
RET_CODE read_clt();
RET_CODE write_clt();
RET_CODE read_srv();
RET_CODE write_srv();

public:
static const int BUF_SIZE = 2048;

// client
char* m_clt_buf;
int m_clt_read_idx;
int m_clt_write_idx;
sockaddr_in m_clt_address;
int m_cltfd;

// server
char* m_srv_buf;
int m_srv_read_idx;
int m_srv_write_idx;
sockaddr_in m_srv_address;
int m_srvfd;

bool m_srv_closed;
};

#endif

conn::conn()
{
m_srvfd = -1;
m_clt_buf = new char[ BUF_SIZE ];
if( !m_clt_buf )
{
throw std::exception();
}
m_srv_buf = new char[ BUF_SIZE ];
if( !m_srv_buf )
{
throw std::exception();
}
reset();
}

conn::~conn()
{
delete [] m_clt_buf;
delete [] m_srv_buf;
}

void conn::init_clt( int sockfd, const sockaddr_in& client_addr )
{
m_cltfd = sockfd;
m_clt_address = client_addr;
}

void conn::init_srv( int sockfd, const sockaddr_in& server_addr )
{
m_srvfd = sockfd;
m_srv_address = server_addr;
}

void conn::reset()
{
m_clt_read_idx = 0;
m_clt_write_idx = 0;
m_srv_read_idx = 0;
m_srv_write_idx = 0;
m_srv_closed = false;
m_cltfd = -1;
memset( m_clt_buf, '\0', BUF_SIZE );
memset( m_srv_buf, '\0', BUF_SIZE );
}

RET_CODE conn::read_clt()
{
int bytes_read = 0;
while( true )
{
if( m_clt_read_idx >= BUF_SIZE )
{
log( LOG_ERR, __FILE__, __LINE__, "%s", "the client read buffer is full, let server write" );
return BUFFER_FULL;
}

bytes_read = recv( m_cltfd, m_clt_buf + m_clt_read_idx, BUF_SIZE - m_clt_read_idx, 0 );
if ( bytes_read == -1 )
{
if( errno == EAGAIN || errno == EWOULDBLOCK )
{
break;
}
return IOERR;
}
else if ( bytes_read == 0 )
{
return CLOSED;
}

m_clt_read_idx += bytes_read;
}
return ( ( m_clt_read_idx - m_clt_write_idx ) > 0 ) ? OK : NOTHING;
}


RET_CODE conn::read_srv()
{
int bytes_read = 0;
while( true )
{
if( m_srv_read_idx >= BUF_SIZE )
{
log( LOG_ERR, __FILE__, __LINE__, "%s", "the server read buffer is full, let client write" );
return BUFFER_FULL;
}

bytes_read = recv( m_srvfd, m_srv_buf + m_srv_read_idx, BUF_SIZE - m_srv_read_idx, 0 );
if ( bytes_read == -1 )
{
if( errno == EAGAIN || errno == EWOULDBLOCK )
{
break;
}
return IOERR;
}
else if ( bytes_read == 0 )
{
log( LOG_ERR, __FILE__, __LINE__, "%s", "the server should not close the persist connection" );
return CLOSED;
}

m_srv_read_idx += bytes_read;
}
return ( ( m_srv_read_idx - m_srv_write_idx ) > 0 ) ? OK : NOTHING;
}

RET_CODE conn::write_srv()
{
int bytes_write = 0;
while( true )
{
if( m_clt_read_idx <= m_clt_write_idx )
{
m_clt_read_idx = 0;
m_clt_write_idx = 0;
return BUFFER_EMPTY;
}

bytes_write = send( m_srvfd, m_clt_buf + m_clt_write_idx, m_clt_read_idx - m_clt_write_idx, 0 );
if ( bytes_write == -1 )
{
if( errno == EAGAIN || errno == EWOULDBLOCK )
{
return TRY_AGAIN;
}
log( LOG_ERR, __FILE__, __LINE__, "write server socket failed, %s", strerror( errno ) );
return IOERR;
}
else if ( bytes_write == 0 )
{
return CLOSED;
}

m_clt_write_idx += bytes_write;
}
}

RET_CODE conn::write_clt()
{
int bytes_write = 0;
while( true )
{
if( m_srv_read_idx <= m_srv_write_idx )
{
m_srv_read_idx = 0;
m_srv_write_idx = 0;
return BUFFER_EMPTY;
}

bytes_write = send( m_cltfd, m_srv_buf + m_srv_write_idx, m_srv_read_idx - m_srv_write_idx, 0 );
if ( bytes_write == -1 )
{
if( errno == EAGAIN || errno == EWOULDBLOCK )
{
return TRY_AGAIN;
}
log( LOG_ERR, __FILE__, __LINE__, "write client socket failed, %s", strerror( errno ) );
return IOERR;
}
else if ( bytes_write == 0 )
{
return CLOSED;
}

m_srv_write_idx += bytes_write;
}
}

log

没啥新意,很普通的 logger

查看更多

Liso(2) httpServer

Log

增加 Log 功能方便调试。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#ifndef LOG_H
#define LOG_H

#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <time.h>

// 整个项目的全局变量
char *logfile; // 文件名
FILE *fp; // 文件 handler

int init_log();
void dump_log(const char *fmt, ...);
void close_log();

#endif

实现比较简单,就是往全局文件里 dump log 字符串。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
// 初始化日志文件
int init_log()
{
fp = fopen(logfile, "a");
if (fp == NULL)
{
printf("[ERROR] log file can not be created");
return -1;
}
return 0;
}

// 写入日志文件
void dump_log(const char *fmt, ...)
{
time_t tmp = time(NULL);
struct tm* cur_time = localtime(&tmp);
if (!cur_time)
{
return;
}
char arg_buffer[LOG_BUFFER_SIZE];
memset(arg_buffer, '\0', LOG_BUFFER_SIZE);
strftime(arg_buffer, LOG_BUFFER_SIZE - 1, "[ %x %X ] ", cur_time);

fwrite(arg_buffer, sizeof(arg_buffer), 1, fp);

va_list(args);
va_start(args, fmt);
vfprintf(fp, fmt, args);
va_end(args);
fprintf(fp, "\n");
fflush(fp);
}

// 关闭日志文件
void close_log()
{
fclose(fp);
}

parse

解析 http 协议采用 flex 和 bison 实现

查看更多

网络编程通用结构体

IPV4

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
struct sockaddr_in {
sa_family_t sin_family; /* AF_INET */
in_port_t sin_port; /* Port number. */
struct in_addr sin_addr; /* Internet address. */

/* Pad to size of `struct sockaddr'. */
unsigned char sin_zero[sizeof (struct sockaddr) -
sizeof (sa_family_t) -
sizeof (in_port_t) -
sizeof (struct in_addr)];
};
typedef uint32_t in_addr_t;
struct in_addr {
in_addr_t s_addr; /* IPv4 address */
};

// 占据 16 个字节

IPV6

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
struct sockaddr_in6 {
sa_family_t sin6_family; /* AF_INET6 */
in_port_t sin6_port; /* Transport layer port # */
uint32_t sin6_flowinfo; /* IPv6 flow information */
struct in6_addr sin6_addr; /* IPv6 address */
uint32_t sin6_scope_id; /* IPv6 scope-id */
};
struct in6_addr {
union {
uint8_t u6_addr8[16];
uint16_t u6_addr16[8];
uint32_t u6_addr32[4];
} in6_u;

#define s6_addr in6_u.u6_addr8
#define s6_addr16 in6_u.u6_addr16
#define s6_addr32 in6_u.u6_addr32
};

通用结构体

sockaddr 16字节

1
2
3
4
struct sockaddr { 
sa_family_t sa_family; /* Address family */
char sa_data[14]; /* protocol-specific address */
};

sockaddr_storage 128字节

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
  /* Structure large enough to hold any socket address 
(with the historical exception of AF_UNIX). 128 bytes reserved. */

#if ULONG_MAX > 0xffffffff
# define __ss_aligntype __uint64_t
#else
# define __ss_aligntype __uint32_t
#endif
#define _SS_SIZE 128
#define _SS_PADSIZE (_SS_SIZE - (2 * sizeof (__ss_aligntype)))

struct sockaddr_storage
{
sa_family_t ss_family; /* Address family */
__ss_aligntype __ss_align; /* Force desired alignment. */
char __ss_padding[_SS_PADSIZE];
};

Liso(1) echo server

liujianhao 带佬的 git repo 真的干货满满,这波开始 Liso 的源码阅读。

首先看 client_pool, 其中管理了连接到 server 的 client 信息。

Client pool

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#ifndef __SERVER_H
#define __SERVER_H

#include "io.h"

// 客户池
typedef struct
{
// 全部
fd_set all_set;
// 准备要读的
fd_set read_fds;
// 最大值
int maxfd;
// 已经准备的个数
int nready;
// 在数组中可获得的最大下标
int maxi;
// 客户数组
int client_fd[FD_SETSIZE];
} client_pool;

void init_pool(int listenfd, client_pool *p);
void add_client_to_pool(int newfd, client_pool *p);
void handle_clients(client_pool *p);
void clear_client(int clientfd, int idx, client_pool *p);

#endif

初始化客户池

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 初始化客户池,刚开始只有 listenfd 才是需要监听的
void init_pool(int listenfd, client_pool *p)
{
FD_ZERO(&p->all_set);
FD_ZERO(&p->read_fds);
FD_SET(listenfd, &p->all_set);
p->maxfd = listenfd;
p->nready = 0;
p->maxi = -1;
for (int i = 0; i < FD_SETSIZE; i++)
{
// -1表示这个位置还没被占用
p->client_fd[i] = -1;
}
}

增加 client

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// 添加客户套接字文件描述符到客户池
void add_client_to_pool(int newfd, client_pool *p)
{
int i;
p->nready--;

for (i = 0; i < FD_SETSIZE; i++)
{
// 先在数组中找到位置存储新到来的fd
if (p->client_fd[i] < 0)
{
p->client_fd[i] = newfd;
FD_SET(newfd, &p->all_set);
p->maxfd = (newfd > p->maxfd) ? newfd : p->maxfd;
p->maxi = (i > p->maxi) ? i : p->maxi;
break;
}
}

// 超过限制
if (i == FD_SETSIZE)
{
printlog("[Client pool] Too many clients!");
}
}

查看更多

SimpleEpollServer源码阅读

AsyncServer

首先看一下 Server 的 data member.

1
2
3
4
5
6
private:
int listen_fd_, epoll_fd_;
epoll_event *events_;
std::map<int, ClientDescriptor *> clients_;
uint32_t timeout_secs_;
time_t last_socket_check_;

AsynceServer 的构造函数如下, 首先初始化了 socket 连接, 绑定端口号,设置 listenfd, 又设置了 epoll 的 event 和 nonblocking。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
AsyncServer(const char *listen_addr, uint16_t listen_port, uint32_t timeout_secs) :
listen_fd_(-1),
epoll_fd_(-1),
timeout_secs_(timeout_secs),
last_socket_check_(0)
{
sockaddr_in sin = { 0 };

sin.sin_addr.s_addr = inet_addr(listen_addr);
sin.sin_family = AF_INET;
sin.sin_port = htons(listen_port);

listen_fd_ = socket(AF_INET, SOCK_STREAM, 0);
if(listen_fd_ <= 0)
throw std::runtime_error("socket() failed, error code: " + std::to_string(errno));

if(bind(listen_fd_, reinterpret_cast<sockaddr *>(&sin), sizeof(sin)))
throw std::runtime_error("bind() failed, error code: " + std::to_string(errno));

if(SetNonblocking(listen_fd_) == false)
throw std::runtime_error("SetNonBlocking() failed, error code: " + std::to_string(errno));

if(listen(listen_fd_, SOMAXCONN) == -1)
throw std::runtime_error("listen() failed, error code: " + std::to_string(errno));

epoll_fd_ = epoll_create1(0);
if(epoll_fd_ == -1)
throw std::runtime_error("epoll_create1() failed, error code: " + std::to_string(errno));

epoll_event e_event;
e_event.events = EPOLLIN;
e_event.data.fd = listen_fd_;

if(epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, listen_fd_, &e_event) == -1)
throw std::runtime_error("epoll_ctl() failed, error code: " + std::to_string(errno));

events_ = new epoll_event[64];
}

构造函数中的 SetNonblocking 的实现如下:

查看更多

yfs-源码剖析(3)--基本文件服务2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
int
yfs_client::mkdir(inum parent, const char *name, mode_t mode, inum &inum)
{
LockGuard lg(m_lc, parent);
std::string data;
std::string dir_name;
if (ec->get(parent, data) != extent_protocol::OK)
{
return IOERR;
}

dir_name = "/" + std::string(name) + "/";
// 目录已经存在
if (data.find(dir_name) != std::string::npos)
{
return EXIST;
}

inum = random_inum(false);
if (ec->put(inum, std::string()) != extent_protocol::OK)
{
return IOERR;
}

data.append(dir_name + filename(inum) + "/");
if (ec->put(parent, data) != extent_protocol::OK)
{
return IOERR;
}

return OK;
}

int yfs_client::unlink(inum parent, const char* name)
{
LockGuard lg(m_lc, parent);
std::string data;
std::string file_name = "/" + std::string(name) + "/";
size_t pos, end, len;
inum inum;

if(ec->get(parent, data) != extent_protocol::OK)
{
return IOERR;
}

// 没有这个文件
if((pos = data.find(file_name)) == std::string::npos)
{
return NOENT;
}

end = data.find_first_of("/", pos+file_name.size());
if(end == std::string::npos)
{
return NOENT;
}
len = end - file_name.size() - pos;
inum = n2i(data.substr(pos+file_name.size(), len));
if(!isfile(inum))
{
return IOERR;
}

// 从目录中移除文件
data.erase(pos, end-pos+1);
if(ec->put(parent, data) != extent_protocol::OK)
{
return IOERR;
}

// 删除文件
if(ec->remove(inum) != extent_protocol::OK)
{
return IOERR;
}

return OK;
}

在 fuse 中对应如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
void
fuseserver_mkdir(fuse_req_t req, fuse_ino_t parent, const char *name,
mode_t mode)
{
struct fuse_entry_param e;
// In yfs, timeouts are always set to 0.0, and generations are always set to 0
e.attr_timeout = 0.0;
e.entry_timeout = 0.0;
e.generation = 0;
// Suppress compiler warning of unused e.
(void) e;

#if 1
yfs_client::inum inum = 0;
yfs_client::status ret;
ret = yfs->mkdir(parent, name, mode, inum);
if(ret == yfs_client::OK)
{
e.ino = inum;
getattr(inum, e.attr);
}
else if(ret == yfs_client::EXIST)
{
fuse_reply_err(req, EEXIST);
return;
}

fuse_reply_entry(req, &e);
#else
fuse_reply_err(req, ENOSYS);
#endif
}

// Remove the file named @name from directory @parent.
// Free the file's extent.
// If the file doesn't exist, indicate error ENOENT.
//
// Do *not* allow unlinking of a directory.
//
void
fuseserver_unlink(fuse_req_t req, fuse_ino_t parent, const char *name)
{

// You fill this in for Lab 3
// Success: fuse_reply_err(req, 0);
// Not found: fuse_reply_err(req, ENOENT);
yfs_client::status ret = yfs->unlink(parent, name);
if(ret == yfs_client::OK)
{
fuse_reply_err(req, 0);
return;
}
fuse_reply_err(req, ENOENT);
}

Locking

  • What to lock?

查看更多

yfs-源码剖析(2)--基本文件服务1

Intro

extent_server 用于存储文件系统所有的数据,有多个客户端与 extent_server 进行通信。

为了实现 extent_server 就需要实现 extent_protocol, extent_client 和 extent_server。 通信流程和之前的锁服务类似。

extent_protocol

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
// extent wire protocol

#ifndef extent_protocol_h
#define extent_protocol_h

#include "rpc.h"

class extent_protocol {
public:
typedef int status;
typedef unsigned long long extentid_t;
enum xxstatus { OK, RPCERR, NOENT, IOERR };
enum rpc_numbers {
put = 0x6001,
get,
getattr,
remove
};

struct attr {
unsigned int atime;
unsigned int mtime;
unsigned int ctime;
unsigned int size;
};
};

inline unmarshall &
operator>>(unmarshall &u, extent_protocol::attr &a)
{
u >> a.atime;
u >> a.mtime;
u >> a.ctime;
u >> a.size;
return u;
}

inline marshall &
operator<<(marshall &m, extent_protocol::attr a)
{
m << a.atime;
m << a.mtime;
m << a.ctime;
m << a.size;
return m;
}

#endif

extent_client

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// extent client interface.

#ifndef extent_client_h
#define extent_client_h

#include <string>
#include "extent_protocol.h"
#include "rpc.h"

class extent_client {
private:
rpcc *cl;

public:
extent_client(std::string dst);

extent_protocol::status get(extent_protocol::extentid_t eid,
std::string &buf);
extent_protocol::status getattr(extent_protocol::extentid_t eid,
extent_protocol::attr &a);
extent_protocol::status put(extent_protocol::extentid_t eid, std::string buf);
extent_protocol::status remove(extent_protocol::extentid_t eid);
};

#endif
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
// RPC stubs for clients to talk to extent_server

#include "extent_client.h"
#include <sstream>
#include <iostream>
#include <stdio.h>
#include <unistd.h>
#include <time.h>

// The calls assume that the caller holds a lock on the extent

extent_client::extent_client(std::string dst)
{
sockaddr_in dstsock;
make_sockaddr(dst.c_str(), &dstsock);
cl = new rpcc(dstsock);
if (cl->bind() != 0) {
printf("extent_client: bind failed\n");
}
}

extent_protocol::status
extent_client::get(extent_protocol::extentid_t eid, std::string &buf)
{
extent_protocol::status ret = extent_protocol::OK;
ret = cl->call(extent_protocol::get, eid, buf);
return ret;
}

extent_protocol::status
extent_client::getattr(extent_protocol::extentid_t eid,
extent_protocol::attr &attr)
{
extent_protocol::status ret = extent_protocol::OK;
ret = cl->call(extent_protocol::getattr, eid, attr);
return ret;
}

extent_protocol::status
extent_client::put(extent_protocol::extentid_t eid, std::string buf)
{
extent_protocol::status ret = extent_protocol::OK;
int r;
ret = cl->call(extent_protocol::put, eid, buf, r);
return ret;
}

extent_protocol::status
extent_client::remove(extent_protocol::extentid_t eid)
{
extent_protocol::status ret = extent_protocol::OK;
int r;
ret = cl->call(extent_protocol::remove, eid, r);
return ret;
}

// 都是套路代码 为了 rpc。。。

查看更多