summaryrefslogtreecommitdiff
path: root/lib/sqfs/data_writer/internal.h
blob: ea66290bfd97328332007652bcbeb926729d1f2f (plain)
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
/* SPDX-License-Identifier: LGPL-3.0-or-later */
/*
 * internal.h
 *
 * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at>
 */
#ifndef INTERNAL_H
#define INTERNAL_H

#include "config.h"

#include "sqfs/data_writer.h"
#include "sqfs/compressor.h"
#include "sqfs/inode.h"
#include "sqfs/table.h"
#include "sqfs/error.h"
#include "sqfs/block.h"
#include "sqfs/io.h"
#include "util.h"

#include <string.h>
#include <stdlib.h>
#include <zlib.h>

#ifdef WITH_PTHREAD
#include <pthread.h>
#endif


#define MK_BLK_HASH(chksum, size) \
	(((sqfs_u64)(size) << 32) | (sqfs_u64)(chksum))

#define INIT_BLOCK_COUNT (128)


typedef struct {
	sqfs_u64 offset;
	sqfs_u64 hash;
} blk_info_t;

typedef struct {
	sqfs_u32 index;
	sqfs_u32 offset;
	sqfs_u64 hash;
} frag_info_t;


#ifdef WITH_PTHREAD
typedef struct {
	sqfs_data_writer_t *shared;
	sqfs_compressor_t *cmp;
	pthread_t thread;
	sqfs_u8 scratch[];
} compress_worker_t;
#endif

struct sqfs_data_writer_t {
	/* synchronization primitives */
#ifdef WITH_PTHREAD
	pthread_mutex_t mtx;
	pthread_cond_t queue_cond;
	pthread_cond_t done_cond;
#endif

	/* needs rw access by worker and main thread */
	sqfs_block_t *queue;
	sqfs_block_t *queue_last;

	sqfs_block_t *done;
	size_t backlog;
	int status;

	/* used by main thread only */
	sqfs_u32 enqueue_id;
	sqfs_u32 dequeue_id;

	unsigned int num_workers;
	size_t max_backlog;

	size_t devblksz;
	sqfs_file_t *file;

	sqfs_fragment_t *fragments;
	size_t num_fragments;
	size_t max_fragments;

	sqfs_u64 start;

	size_t file_start;
	size_t num_blocks;
	size_t max_blocks;
	blk_info_t *blocks;
	sqfs_compressor_t *cmp;

	sqfs_block_t *frag_block;
	frag_info_t *frag_list;
	size_t frag_list_num;
	size_t frag_list_max;

	const sqfs_block_hooks_t *hooks;
	void *user_ptr;

	/* file API */
	sqfs_inode_generic_t *inode;
	sqfs_block_t *blk_current;
	sqfs_u32 blk_flags;
	size_t blk_index;

	/* used only by workers */
	size_t max_block_size;

#ifdef WITH_PTHREAD
	compress_worker_t *workers[];
#else
	sqfs_u8 scratch[];
#endif
};

SQFS_INTERNAL int process_completed_block(sqfs_data_writer_t *proc,
					  sqfs_block_t *block);

SQFS_INTERNAL
int process_completed_fragment(sqfs_data_writer_t *proc, sqfs_block_t *frag,
			       sqfs_block_t **blk_out);

SQFS_INTERNAL void free_blk_list(sqfs_block_t *list);

SQFS_INTERNAL
int data_writer_init(sqfs_data_writer_t *proc, size_t max_block_size,
		     sqfs_compressor_t *cmp, unsigned int num_workers,
		     size_t max_backlog, size_t devblksz, sqfs_file_t *file);

SQFS_INTERNAL void data_writer_cleanup(sqfs_data_writer_t *proc);

SQFS_INTERNAL
void data_writer_store_done(sqfs_data_writer_t *proc, sqfs_block_t *blk,
			    int status);

SQFS_INTERNAL
sqfs_block_t *data_writer_next_work_item(sqfs_data_writer_t *proc);

SQFS_INTERNAL
int data_writer_do_block(sqfs_block_t *block, sqfs_compressor_t *cmp,
			 sqfs_u8 *scratch, size_t scratch_size);

SQFS_INTERNAL
int test_and_set_status(sqfs_data_writer_t *proc, int status);

SQFS_INTERNAL
int data_writer_enqueue(sqfs_data_writer_t *proc, sqfs_block_t *block);

#endif /* INTERNAL_H */