-
Notifications
You must be signed in to change notification settings - Fork 11
/
Copy pathdatindex.h
168 lines (142 loc) · 3.9 KB
/
datindex.h
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
/* file: datindex.h
*
* 世界共通インデクスの定義
*
* $Id: datindex.h,v 1.7 2001/09/04 07:26:48 2ch Exp $ */
#ifndef DATINDEX_H__
#define DATINDEX_H__
#include <time.h>
#include <sys/stat.h>
#define DATINDEX_VERSION 1
/*
* 効率を考えて、インデクスはなるべく4096バイト(page size)以内に
* 収まるようにする。逆に言うと、4096バイトより小さくしても、
* メモリ効率・ディスク容量の点でメリットはない。
* (Linux ext2は、fragmentを作らないはずなので、
* minimum allocation unitは4096バイトのハズ)
*
* 【運用の最低約束】
*
* * version が0のインデクスに遭遇、
* あるいはインデクスのサイズが0だったら、
* 基本的に何もせず、インデクスに頼らず自力で処理する。
* ただし、versionが0のまま一定時間経過したものは、
* 廃棄-再作成を行うべき。(作成途中で氏んだと考えれ)
* * version が知ってるものより大きいときは、
* 何もせず、自力で処理する。
* * version が知ってるものより小さい場合は、
* 廃棄して新規作成。
*
* 【新規作成のやり方】
* * creat(2)でつくれ。
* creat()に勝ったプロセスが責任を持って
* インデクスを構築しる!
* creat()で負けたプロセスは、自力で処理しる!
* インデクス構築が終わったら、versionをセットしる!
*
* 【オープンのやり方】
* * MAP_SHAREDで開くべし。
*
* 【古いバージョンの廃棄のやり方】
* * ファイルをディレクトリからunlink
* * あとは【新規作成】へ。
*
*/
/* 想定記事総数
キリのいい数字であるべきだ */
#define DATINDEX_MAX_ARTICLES 1024
/* インデクス単位
CHUNK_NUMの約数であるべきだ */
#define DATINDEX_CHUNK_SIZE 10
#define DATINDEX_IDX_SIZE ((DATINDEX_MAX_ARTICLES + DATINDEX_CHUNK_SIZE - 1) \
/ DATINDEX_CHUNK_SIZE)
/* インデクス
サイズが4096を超えるのは歓迎できない */
typedef struct DATINDEX
{
/* バージョン情報。破壊操作のセマフォにもなっている */
unsigned long volatile version;
/* 発言数
chunk idx更新のセマフォにもなっている */
unsigned long linenum;
/* .dat の最終更新時刻 */
time_t lastmod;
/* スレタイトルへのオフセット */
unsigned title_ofs;
/* インデクス
本来ならば、全記事に対して
L-Mを持ちたいところなのだが、
そうするとサイズが大きくなりすぎて鬱だ…
各記事のL-Mは、chunk L-Mからの差分(16bit)で
持つようにし、差が18時間以上あるものは
特別扱いする、というkludgeも考えられるが… */
struct
{
unsigned nextofs; /* 次chunkへのオフセット */
time_t lastmod; /* chunkの最新更新 */
unsigned valid_bitmap; /* 有効発言: LSBから読め */
long pad; /* うめぐさ */
} idx[DATINDEX_IDX_SIZE];
/* XXX うめぐさ1 */
unsigned pad1[607];
/* シグネチャ */
unsigned long signature;
} DATINDEX;
struct DATINDEX_STRING
{
char const *p;
int len;
};
struct DATINDEX_LINE
{
/* これらのポインタ同士を再計算すべきではない XXX */
struct DATINDEX_STRING name;
struct DATINDEX_STRING mailto;
struct DATINDEX_STRING date;
struct DATINDEX_STRING text;
int len; /* 未計算の時は 0 が入る */
time_t lastmod; /* あぼーん時には 0 を入れれ */
};
/* index管理
べつにグローバル変数でもいいけどね */
typedef struct DATINDEX_OBJ
{
/* .dat本体 */
struct stat dat_stat;
char *private_dat;
/* .datを読んで生成されるテーブル */
struct DATINDEX_LINE *line;
/* lineの個数 */
int linenum;
/* インデクス */
DATINDEX volatile *shared_idx;
} DATINDEX_OBJ;
/* 注意: i386 では動きませーん(藁 */
#define DATINDEX_CMPXCHG(sem, cur, new) \
({ \
long eax; \
__asm__ ("cmpxchg %2,%3": \
"=a"(eax) : \
"0"(cur), \
"r"(new), \
"g"(sem)); \
eax; \
})
/* 命名規則を間違えた…鬱
公開インタフェイスは、
<module>_<method>()
って命名にするようにしよう、今後は。 */
/* インデクスを dat に読み込む
dat は完全に初期化が行われる */
extern int datindex_open(DATINDEX_OBJ *dat,
char const *bs, long ky);
/* lastmodを拾い上げる
first は、!is_nofirst() であることに注意 */
extern time_t datindex_lastmod(DATINDEX_OBJ const *dat,
int first, /* 1番目を含める */
int st,
int to);
/* 実は漏れ、C++大好きなんだ…
なんとなくそれを匂わせる書き方になってるでしょ?(鬱
(6411) */
#endif /* DATINDEX_H__ */