forked from devttys0/sasquatch
-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathcaches-queues-lists.h
200 lines (181 loc) · 5.49 KB
/
caches-queues-lists.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
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
#ifndef CACHES_QUEUES_LISTS_H
#define CACHES_QUEUES_LISTS_H
/*
* Create a squashfs filesystem. This is a highly compressed read only
* filesystem.
*
* Copyright (c) 2013, 2014
* Phillip Lougher <[email protected]>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2,
* or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* caches-queues-lists.h
*/
#define INSERT_LIST(NAME, TYPE) \
void insert_##NAME##_list(TYPE **list, TYPE *entry) { \
if(*list) { \
entry->NAME##_next = *list; \
entry->NAME##_prev = (*list)->NAME##_prev; \
(*list)->NAME##_prev->NAME##_next = entry; \
(*list)->NAME##_prev = entry; \
} else { \
*list = entry; \
entry->NAME##_prev = entry->NAME##_next = entry; \
} \
}
#define REMOVE_LIST(NAME, TYPE) \
void remove_##NAME##_list(TYPE **list, TYPE *entry) { \
if(entry->NAME##_prev == entry && entry->NAME##_next == entry) { \
/* only this entry in the list */ \
*list = NULL; \
} else if(entry->NAME##_prev != NULL && entry->NAME##_next != NULL) { \
/* more than one entry in the list */ \
entry->NAME##_next->NAME##_prev = entry->NAME##_prev; \
entry->NAME##_prev->NAME##_next = entry->NAME##_next; \
if(*list == entry) \
*list = entry->NAME##_next; \
} \
entry->NAME##_prev = entry->NAME##_next = NULL; \
}
#define INSERT_HASH_TABLE(NAME, TYPE, HASH_FUNCTION, FIELD, LINK) \
void insert_##NAME##_hash_table(TYPE *container, struct file_buffer *entry) \
{ \
int hash = HASH_FUNCTION(entry->FIELD); \
\
entry->LINK##_next = container->hash_table[hash]; \
container->hash_table[hash] = entry; \
entry->LINK##_prev = NULL; \
if(entry->LINK##_next) \
entry->LINK##_next->LINK##_prev = entry; \
}
#define REMOVE_HASH_TABLE(NAME, TYPE, HASH_FUNCTION, FIELD, LINK) \
void remove_##NAME##_hash_table(TYPE *container, struct file_buffer *entry) \
{ \
if(entry->LINK##_prev) \
entry->LINK##_prev->LINK##_next = entry->LINK##_next; \
else \
container->hash_table[HASH_FUNCTION(entry->FIELD)] = \
entry->LINK##_next; \
if(entry->LINK##_next) \
entry->LINK##_next->LINK##_prev = entry->LINK##_prev; \
\
entry->LINK##_prev = entry->LINK##_next = NULL; \
}
#define HASH_SIZE 65536
#define CALCULATE_HASH(n) ((n) & 0xffff)
/* struct describing a cache entry passed between threads */
struct file_buffer {
union {
long long index;
long long sequence;
};
long long file_size;
union {
long long block;
unsigned short checksum;
};
struct cache *cache;
union {
struct file_info *dupl_start;
struct file_buffer *hash_next;
};
union {
int duplicate;
struct file_buffer *hash_prev;
};
union {
struct {
struct file_buffer *free_next;
struct file_buffer *free_prev;
};
struct {
struct file_buffer *seq_next;
struct file_buffer *seq_prev;
};
};
int size;
int c_byte;
char used;
char fragment;
char error;
char locked;
char wait_on_unlock;
char noD;
char data[0];
};
/* struct describing queues used to pass data between threads */
struct queue {
int size;
int readp;
int writep;
pthread_mutex_t mutex;
pthread_cond_t empty;
pthread_cond_t full;
void **data;
};
/*
* struct describing seq_queues used to pass data between the read
* thread and the deflate and main threads
*/
struct seq_queue {
int fragment_count;
int block_count;
struct file_buffer *hash_table[HASH_SIZE];
pthread_mutex_t mutex;
pthread_cond_t wait;
};
/* Cache status struct. Caches are used to keep
track of memory buffers passed between different threads */
struct cache {
int max_buffers;
int count;
int buffer_size;
int noshrink_lookup;
int first_freelist;
union {
int used;
int max_count;
};
pthread_mutex_t mutex;
pthread_cond_t wait_for_free;
pthread_cond_t wait_for_unlock;
struct file_buffer *free_list;
struct file_buffer *hash_table[HASH_SIZE];
};
extern struct queue *queue_init(int);
extern void queue_put(struct queue *, void *);
extern void *queue_get(struct queue *);
extern int queue_empty(struct queue *);
extern void queue_flush(struct queue *);
extern void dump_queue(struct queue *);
extern struct seq_queue *seq_queue_init();
extern void seq_queue_put(struct seq_queue *, struct file_buffer *);
extern void dump_seq_queue(struct seq_queue *, int);
extern struct file_buffer *seq_queue_get(struct seq_queue *);
extern void seq_queue_flush(struct seq_queue *);
extern struct cache *cache_init(int, int, int, int);
extern struct file_buffer *cache_lookup(struct cache *, long long);
extern struct file_buffer *cache_get(struct cache *, long long);
extern struct file_buffer *cache_get_nohash(struct cache *);
extern void cache_hash(struct file_buffer *, long long);
extern void cache_block_put(struct file_buffer *);
extern void dump_cache(struct cache *);
extern struct file_buffer *cache_get_nowait(struct cache *, long long);
extern struct file_buffer *cache_lookup_nowait(struct cache *, long long,
char *);
extern void cache_wait_unlock(struct file_buffer *);
extern void cache_unlock(struct file_buffer *);
extern int first_freelist;
#endif