aboutsummaryrefslogtreecommitdiffstats
path: root/libsemanage/src/database_activedb.c
blob: 1cce0b8294c638db119f6edcc952f45f34f90f85 (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
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
/* Copyright (C) 2005 Red Hat, Inc. */

/* Object: dbase_activedb_t (Active/Kernel)
 * Extends: dbase_llist_t (Linked List) 
 * Implements: dbase_t (Database)
 */

struct dbase_activedb;
typedef struct dbase_activedb dbase_t;
#define DBASE_DEFINED

#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "debug.h"
#include "handle.h"
#include "database_activedb.h"
#include "database_llist.h"

/* ACTIVEDB dbase */
struct dbase_activedb {

	/* Parent object - must always be 
	 * the first field - here we are using
	 * a linked list to store the records */
	dbase_llist_t llist;

	/* ACTIVEDB extension */
	record_activedb_table_t *ratable;
};

static int dbase_activedb_cache(semanage_handle_t * handle,
				dbase_activedb_t * dbase)
{

	record_table_t *rtable = dbase_llist_get_rtable(&dbase->llist);
	record_activedb_table_t *ratable = dbase->ratable;

	record_t **records = NULL;
	unsigned int rcount = 0;
	unsigned int i = 0;

	/* Already cached */
	if (!dbase_llist_needs_resync(handle, &dbase->llist))
		return STATUS_SUCCESS;

	/* Update cache serial */
	dbase_llist_cache_init(&dbase->llist);
	if (dbase_llist_set_serial(handle, &dbase->llist) < 0)
		goto err;

	/* Fetch the entire list */
	if (ratable->read_list(handle, &records, &rcount) < 0)
		goto err;

	/* Add records one by one */
	for (; i < rcount; i++) {
		if (dbase_llist_cache_prepend(handle, &dbase->llist, records[i])
		    < 0)
			goto err;
		rtable->free(records[i]);
	}

	free(records);
	return STATUS_SUCCESS;

      err:
	ERR(handle, "could not cache active database");
	for (; i < rcount; i++)
		rtable->free(records[i]);
	dbase_llist_drop_cache(&dbase->llist);
	free(records);
	return STATUS_ERR;
}

static int dbase_activedb_flush(semanage_handle_t * handle,
				dbase_activedb_t * dbase)
{

	record_table_t *rtable = dbase_llist_get_rtable(&dbase->llist);
	record_activedb_table_t *ratable = dbase->ratable;

	record_t **records = NULL;
	unsigned int rcount = 0;
	unsigned int i;

	/* Not cached, or not modified - flush is not necessary */
	if (!dbase_llist_is_modified(&dbase->llist))
		return STATUS_SUCCESS;

	/* Fetch list */
	if (dbase_llist_list(handle, &dbase->llist, &records, &rcount) < 0)
		goto err;

	/* Commit */
	if (ratable->commit_list(handle, records, rcount) < 0)
		goto err;

	for (i = 0; i < rcount; i++)
		rtable->free(records[i]);
	free(records);
	dbase_llist_set_modified(&dbase->llist, 0);
	return STATUS_SUCCESS;

      err:
	for (i = 0; i < rcount; i++)
		rtable->free(records[i]);
	free(records);
	ERR(handle, "could not flush active database");
	return STATUS_ERR;
}

int dbase_activedb_init(semanage_handle_t * handle,
			record_table_t * rtable,
			record_activedb_table_t * ratable,
			dbase_activedb_t ** dbase)
{

	dbase_activedb_t *tmp_dbase =
	    (dbase_activedb_t *) malloc(sizeof(dbase_activedb_t));

	if (!tmp_dbase)
		goto omem;

	tmp_dbase->ratable = ratable;
	dbase_llist_init(&tmp_dbase->llist, rtable, &SEMANAGE_ACTIVEDB_DTABLE);

	*dbase = tmp_dbase;

	return STATUS_SUCCESS;

      omem:
	ERR(handle, "out of memory, could not initialize active database");
	free(tmp_dbase);
	return STATUS_ERR;
}

/* Release dbase resources */
void dbase_activedb_release(dbase_activedb_t * dbase)
{

	dbase_llist_drop_cache(&dbase->llist);
	free(dbase);
}

/* ACTIVEDB dbase - method table implementation */
dbase_table_t SEMANAGE_ACTIVEDB_DTABLE = {

	/* Cache/Transactions */
	.cache = dbase_activedb_cache,
	.drop_cache = (void *)dbase_llist_drop_cache,
	.flush = dbase_activedb_flush,
	.is_modified = (void *)dbase_llist_is_modified,

	/* Database API */
	.iterate = (void *)dbase_llist_iterate,
	.exists = (void *)dbase_llist_exists,
	.list = (void *)dbase_llist_list,
	.add = (void *)dbase_llist_add,
	.set = (void *)dbase_llist_set,
	.del = (void *)dbase_llist_del,
	.clear = (void *)dbase_llist_clear,
	.modify = (void *)dbase_llist_modify,
	.query = (void *)dbase_llist_query,
	.count = (void *)dbase_llist_count,

	/* Polymorphism */
	.get_rtable = (void *)dbase_llist_get_rtable
};