Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 : : /*
3 : : * Copyright 2010 Couchbase, Inc
4 : : *
5 : : * Licensed under the Apache License, Version 2.0 (the "License");
6 : : * you may not use this file except in compliance with the License.
7 : : * You may obtain a copy of the License at
8 : : *
9 : : * http://www.apache.org/licenses/LICENSE-2.0
10 : : *
11 : : * Unless required by applicable law or agreed to in writing, software
12 : : * distributed under the License is distributed on an "AS IS" BASIS,
13 : : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 : : * See the License for the specific language governing permissions and
15 : : * limitations under the License.
16 : : */
17 : :
18 : : #include <stdlib.h>
19 : : #include <string.h>
20 : : #include <assert.h>
21 : : #include <stdint.h>
22 : :
23 : : #include "libforestdb/forestdb.h"
24 : : #include "fdb_internal.h"
25 : : #include "internal_types.h"
26 : : #include "filemgr.h"
27 : : #include "common.h"
28 : : #include "list.h"
29 : : #include "wal.h"
30 : : #include "memleak.h"
31 : :
32 : : LIBFDB_API
33 : 1226 : fdb_status fdb_begin_transaction(fdb_file_handle *fhandle,
34 : : fdb_isolation_level_t isolation_level)
35 : : {
36 : 1226 : fdb_kvs_handle *handle = fhandle->root;
37 : : struct filemgr *file;
38 : :
39 [ - + ]: 1226 : if (handle->txn) {
40 : : // transaction already exists
41 : 0 : return FDB_RESULT_TRANSACTION_FAIL;
42 : : }
43 [ + + ]: 1226 : if (handle->kvs) {
44 [ - + ]: 1225 : if (handle->kvs->type == KVS_SUB) {
45 : : // deny transaction on sub handle
46 : 0 : return FDB_RESULT_INVALID_HANDLE;
47 : : }
48 : : }
49 : :
50 : 1226 : fdb_check_file_reopen(handle);
51 : 1226 : filemgr_mutex_lock(handle->file);
52 : 1226 : fdb_sync_db_header(handle);
53 : 1226 : fdb_link_new_file(handle);
54 : :
55 [ - + ]: 1226 : if (filemgr_is_rollback_on(handle->file)) {
56 : : // deny beginning transaction during rollback
57 : 0 : filemgr_mutex_unlock(handle->file);
58 : 0 : return FDB_RESULT_FAIL_BY_ROLLBACK;
59 : : }
60 : :
61 [ + + ]: 1226 : if (handle->new_file == NULL) {
62 : 1004 : file = handle->file;
63 : : } else {
64 : : // compaction is being performed and new file exists
65 : : // relay lock
66 : 222 : filemgr_mutex_lock(handle->new_file);
67 : 222 : filemgr_mutex_unlock(handle->file);
68 : 222 : file = handle->new_file;
69 : : }
70 : :
71 : 1226 : handle->txn = (fdb_txn*)malloc(sizeof(fdb_txn));
72 : : handle->txn->wrapper = (struct wal_txn_wrapper *)
73 : 1226 : malloc(sizeof(struct wal_txn_wrapper));
74 : 1226 : handle->txn->wrapper->txn = handle->txn;
75 : 1226 : handle->txn->handle = handle;
76 [ + + ]: 1226 : if (filemgr_get_file_status(handle->file) != FILE_COMPACT_OLD) {
77 : : // keep previous header's BID
78 : 1004 : handle->txn->prev_hdr_bid = handle->last_hdr_bid;
79 : : } else {
80 : : // if file status is COMPACT_OLD,
81 : : // then this transaction will work on new file, and
82 : : // there is no previous header until the compaction is done.
83 : 222 : handle->txn->prev_hdr_bid = BLK_NOT_FOUND;
84 : : }
85 : 1226 : handle->txn->items = (struct list *)malloc(sizeof(struct list));
86 : 1226 : handle->txn->isolation = isolation_level;
87 : 1226 : list_init(handle->txn->items);
88 : 1226 : wal_add_transaction(file, handle->txn);
89 : :
90 : 1226 : filemgr_mutex_unlock(file);
91 : :
92 : 1226 : return FDB_RESULT_SUCCESS;
93 : : }
94 : :
95 : : LIBFDB_API
96 : 5 : fdb_status fdb_abort_transaction(fdb_file_handle *fhandle)
97 : : {
98 : 5 : return _fdb_abort_transaction(fhandle->root);
99 : : }
100 : :
101 : 7 : fdb_status _fdb_abort_transaction(fdb_kvs_handle *handle)
102 : : {
103 : : struct filemgr *file;
104 : :
105 [ - + ]: 7 : if (handle->txn == NULL) {
106 : : // there is no transaction started
107 : 0 : return FDB_RESULT_TRANSACTION_FAIL;
108 : : }
109 [ + + ]: 7 : if (handle->kvs) {
110 [ - + ]: 6 : if (handle->kvs->type == KVS_SUB) {
111 : : // deny transaction on sub handle
112 : 0 : return FDB_RESULT_INVALID_HANDLE;
113 : : }
114 : : }
115 : :
116 : 7 : fdb_check_file_reopen(handle);
117 [ + - ]: 7 : if (handle->new_file == NULL) {
118 : 7 : file = handle->file;
119 : 7 : filemgr_mutex_lock(file);
120 : 7 : fdb_sync_db_header(handle);
121 : 7 : fdb_link_new_file(handle);
122 [ - + ]: 7 : if (handle->new_file) {
123 : : // compaction is being performed and new file exists
124 : : // relay lock
125 : 0 : filemgr_mutex_lock(handle->new_file);
126 : 0 : filemgr_mutex_unlock(handle->file);
127 : : // reset FILE
128 : 0 : file = handle->new_file;
129 : : }
130 : : } else {
131 : 0 : file = handle->new_file;
132 : 0 : filemgr_mutex_lock(file);
133 : 0 : fdb_sync_db_header(handle);
134 : : }
135 : :
136 : 7 : wal_discard(file, handle->txn);
137 : 7 : wal_remove_transaction(file, handle->txn);
138 : :
139 : 7 : free(handle->txn->items);
140 : 7 : free(handle->txn->wrapper);
141 : 7 : free(handle->txn);
142 : 7 : handle->txn = NULL;
143 : :
144 : 7 : filemgr_mutex_unlock(file);
145 : :
146 : 7 : return FDB_RESULT_SUCCESS;
147 : : }
148 : :
149 : : LIBFDB_API
150 : 1219 : fdb_status fdb_end_transaction(fdb_file_handle *fhandle,
151 : : fdb_commit_opt_t opt)
152 : : {
153 : 1219 : fdb_kvs_handle *handle = fhandle->root;
154 : : struct filemgr *file;
155 : :
156 [ - + ]: 1219 : if (handle->txn == NULL) {
157 : : // there is no transaction started
158 : 0 : return FDB_RESULT_TRANSACTION_FAIL;
159 : : }
160 [ + - ]: 1219 : if (handle->kvs) {
161 [ - + ]: 1219 : if (handle->kvs->type == KVS_SUB) {
162 : : // deny transaction on sub handle
163 : 0 : return FDB_RESULT_INVALID_HANDLE;
164 : : }
165 : : }
166 : :
167 : 1219 : fdb_status fs = FDB_RESULT_SUCCESS;
168 [ + + ]: 1219 : if (list_begin(handle->txn->items)) {
169 : 1218 : fs = _fdb_commit(handle, opt);
170 : : }
171 : :
172 [ + - ]: 1219 : if (fs == FDB_RESULT_SUCCESS) {
173 : 1219 : fdb_check_file_reopen(handle);
174 [ + + ]: 1219 : if (handle->new_file == NULL) {
175 : 997 : file = handle->file;
176 : 997 : filemgr_mutex_lock(file);
177 : 997 : fdb_sync_db_header(handle);
178 : 997 : fdb_link_new_file(handle);
179 [ + + ]: 997 : if (handle->new_file) {
180 : : // compaction is being performed and new file exists
181 : : // relay lock
182 : 3 : filemgr_mutex_lock(handle->new_file);
183 : 3 : filemgr_mutex_unlock(handle->file);
184 : : // reset FILE
185 : 3 : file = handle->new_file;
186 : : }
187 : : } else {
188 : 222 : file = handle->new_file;
189 : 222 : filemgr_mutex_lock(file);
190 : 222 : fdb_sync_db_header(handle);
191 : : }
192 : :
193 : 1219 : wal_remove_transaction(file, handle->txn);
194 : :
195 : 1219 : free(handle->txn->items);
196 : 1219 : free(handle->txn->wrapper);
197 : 1219 : free(handle->txn);
198 : 1219 : handle->txn = NULL;
199 : :
200 : 1219 : filemgr_mutex_unlock(file);
201 : : }
202 : 1219 : return fs;
203 : : }
|