00001
00039 #include "kblock.h"
00040
00041 #define LOG_LEVEL LOG_LVL_ERR
00042 #define LOG_FORMAT LOG_FMT_VERBOSE
00043
00044 #include <cfg/log.h>
00045 #include <string.h>
00046
00047 INLINE size_t kblock_readDirect(struct KBlock *b, block_idx_t index, void *buf, size_t offset, size_t size)
00048 {
00049 KB_ASSERT_METHOD(b, readDirect);
00050 ASSERT(index < b->blk_cnt);
00051 return b->priv.vt->readDirect(b, b->priv.blk_start + index, buf, offset, size);
00052 }
00053
00054 INLINE size_t kblock_writeDirect(struct KBlock *b, block_idx_t index, const void *buf, size_t offset, size_t size)
00055 {
00056 KB_ASSERT_METHOD(b, writeDirect);
00057 ASSERT(index < b->blk_cnt);
00058 return b->priv.vt->writeDirect(b, b->priv.blk_start + index, buf, offset, size);
00059 }
00060
00061 INLINE size_t kblock_readBuf(struct KBlock *b, void *buf, size_t offset, size_t size)
00062 {
00063 KB_ASSERT_METHOD(b, readBuf);
00064 ASSERT(offset + size <= b->blk_size);
00065
00066 return b->priv.vt->readBuf(b, buf, offset, size);
00067 }
00068
00069 INLINE size_t kblock_writeBuf(struct KBlock *b, const void *buf, size_t offset, size_t size)
00070 {
00071 KB_ASSERT_METHOD(b, writeBuf);
00072 ASSERT(offset + size <= b->blk_size);
00073 return b->priv.vt->writeBuf(b, buf, offset, size);
00074 }
00075
00076 INLINE int kblock_load(struct KBlock *b, block_idx_t index)
00077 {
00078 KB_ASSERT_METHOD(b, load);
00079 ASSERT(index < b->blk_cnt);
00080
00081 LOG_INFO("index %ld\n", index);
00082 return b->priv.vt->load(b, b->priv.blk_start + index);
00083 }
00084
00085 INLINE int kblock_store(struct KBlock *b, block_idx_t index)
00086 {
00087 KB_ASSERT_METHOD(b, store);
00088 ASSERT(index < b->blk_cnt);
00089
00090 LOG_INFO("index %ld\n", index);
00091 return b->priv.vt->store(b, b->priv.blk_start + index);
00092 }
00093
00094 INLINE void kblock_setDirty(struct KBlock *b, bool dirty)
00095 {
00096 if (dirty)
00097 b->priv.flags |= KB_CACHE_DIRTY;
00098 else
00099 b->priv.flags &= ~KB_CACHE_DIRTY;
00100 }
00101
00102
00103 size_t kblock_read(struct KBlock *b, block_idx_t idx, void *buf, size_t offset, size_t size)
00104 {
00105 ASSERT(b);
00106 ASSERT(buf);
00107 ASSERT(offset + size <= b->blk_size);
00108 LOG_INFO("blk_idx %ld, offset %u, size %u\n", idx, offset, size);
00109
00110 if (kblock_buffered(b) && idx == b->priv.curr_blk)
00111 return kblock_readBuf(b, buf, offset, size);
00112 else
00113 return kblock_readDirect(b, idx, buf, offset, size);
00114 }
00115
00116
00117 int kblock_flush(struct KBlock *b)
00118 {
00119 ASSERT(b);
00120
00121 if (!kblock_buffered(b))
00122 return 0;
00123
00124 if (kblock_cacheDirty(b))
00125 {
00126 LOG_INFO("flushing block %ld\n", b->priv.curr_blk);
00127 if (kblock_store(b, b->priv.curr_blk) == 0)
00128 kblock_setDirty(b, false);
00129 else
00130 return EOF;
00131 }
00132 return 0;
00133 }
00134
00135
00136 static bool kblock_loadPage(struct KBlock *b, block_idx_t idx)
00137 {
00138 ASSERT(b);
00139
00140 if (idx != b->priv.curr_blk)
00141 {
00142 LOG_INFO("loading block %ld\n", idx);
00143 if (kblock_flush(b) != 0 || kblock_load(b, idx) != 0)
00144 return false;
00145
00146 b->priv.curr_blk = idx;
00147 }
00148 return true;
00149 }
00150
00151
00152 int kblock_trim(struct KBlock *b, block_idx_t start, block_idx_t count)
00153 {
00154 ASSERT(start + count <= b->blk_cnt);
00155
00156 if (kblock_buffered(b))
00157 {
00158 if (!kblock_loadPage(b, start))
00159 return EOF;
00160 }
00161
00162 b->priv.blk_start += start;
00163 b->priv.curr_blk = 0;
00164 b->blk_cnt = count;
00165 return 0;
00166 }
00167
00168
00169 size_t kblock_write(struct KBlock *b, block_idx_t idx, const void *buf, size_t offset, size_t size)
00170 {
00171 ASSERT(b);
00172 ASSERT(buf);
00173 ASSERT(idx < b->blk_cnt);
00174 ASSERT(offset + size <= b->blk_size);
00175
00176 LOG_INFO("blk_idx %ld, offset %u, size %u\n", idx, offset, size);
00177
00178 if (kblock_buffered(b))
00179 {
00180 if (!kblock_loadPage(b, idx))
00181 return 0;
00182
00183 kblock_setDirty(b, true);
00184 return kblock_writeBuf(b, buf, offset, size);
00185 }
00186 else
00187 {
00188 #ifdef _DEBUG
00189 if (offset != 0 || size != b->blk_size)
00190 ASSERT(kblock_partialWrite(b));
00191 #endif
00192 return kblock_writeDirect(b, idx, buf, offset, size);
00193 }
00194 }
00195
00196 int kblock_copy(struct KBlock *b, block_idx_t src, block_idx_t dest)
00197 {
00198 ASSERT(b);
00199 ASSERT(src < b->blk_cnt);
00200 ASSERT(dest < b->blk_cnt);
00201
00202 if (kblock_buffered(b))
00203 {
00204 if (!kblock_loadPage(b, src))
00205 return EOF;
00206
00207 b->priv.curr_blk = dest;
00208 kblock_setDirty(b, true);
00209 return 0;
00210 }
00211 else if (kblock_partialWrite(b))
00212 {
00213 uint8_t buf[16];
00214 size_t blk_size = b->blk_size;
00215 size_t offset = 0;
00216
00217 while (blk_size)
00218 {
00219 size_t size = MIN(sizeof(buf), blk_size);
00220 if (kblock_readDirect(b, src, buf, offset, size) != size)
00221 return EOF;
00222 if (kblock_writeDirect(b, dest, buf, offset, size) != size)
00223 return EOF;
00224
00225 blk_size -= size;
00226 offset += size;
00227 }
00228 return 0;
00229 }
00230 else
00231 {
00232 ASSERT(0);
00233 return EOF;
00234 }
00235 }
00236
00237 int kblock_swLoad(struct KBlock *b, block_idx_t index)
00238 {
00239
00240
00241
00242
00243
00244
00245 ASSERT(index >= b->priv.blk_start);
00246 return (kblock_readDirect(b, index - b->priv.blk_start, b->priv.buf, 0, b->blk_size) == b->blk_size) ? 0 : EOF;
00247 }
00248
00249 int kblock_swStore(struct KBlock *b, block_idx_t index)
00250 {
00251
00252
00253
00254
00255
00256
00257 ASSERT(index >= b->priv.blk_start);
00258 return (kblock_writeDirect(b, index - b->priv.blk_start, b->priv.buf, 0, b->blk_size) == b->blk_size) ? 0 : EOF;
00259 }
00260
00261 size_t kblock_swReadBuf(struct KBlock *b, void *buf, size_t offset, size_t size)
00262 {
00263 ASSERT(buf);
00264 ASSERT(offset + size <= b->blk_size);
00265
00266 memcpy(buf, (uint8_t *)b->priv.buf + offset, size);
00267 return size;
00268 }
00269
00270 size_t kblock_swWriteBuf(struct KBlock *b, const void *buf, size_t offset, size_t size)
00271 {
00272 ASSERT(buf);
00273 ASSERT(offset + size <= b->blk_size);
00274 memcpy((uint8_t *)b->priv.buf + offset, buf, size);
00275 return size;
00276 }
00277
00278 int kblock_swClose(UNUSED_ARG(struct KBlock, *b))
00279 {
00280 return 0;
00281 }