4 * Copyright (c) 2009-2010 project bchan
6 * This software is provided 'as-is', without any express or implied
7 * warranty. In no event will the authors be held liable for any damages
8 * arising from the use of this software.
10 * Permission is granted to anyone to use this software for any purpose,
11 * including commercial applications, and to alter it and redistribute it
12 * freely, subject to the following restrictions:
14 * 1. The origin of this software must not be misrepresented; you must not
15 * claim that you wrote the original software. If you use this software
16 * in a product, an acknowledgment in the product documentation would be
17 * appreciated but is not required.
19 * 2. Altered source versions must be plainly marked as such, and must not be
20 * misrepresented as being the original software.
22 * 3. This notice may not be removed or altered from any source
32 #include <btron/btron.h>
33 #include <bsys/queue.h>
36 #include "residhash.h"
38 typedef struct datcache_data_t_ datcache_data_t;
40 struct datcache_data_t_ {
49 datcache_data_t datalist;
51 datcache_datareadcontext_t *context;
62 residhash_t residhash;
65 struct datcache_datareadcontext_t_ {
67 datcache_data_t *current;
71 LOCAL datcache_data_t* datcache_data_next(datcache_data_t *data)
73 return (datcache_data_t*)data->queue.next;
76 LOCAL datcache_data_t* datcache_data_new(UB *data, W len)
78 datcache_data_t *cache_data;
80 cache_data = malloc(sizeof(datcache_data_t));
81 if (cache_data == NULL) {
84 cache_data->data = malloc(sizeof(UB)*len);
85 if (cache_data->data == NULL) {
89 memcpy(cache_data->data, data, len);
90 cache_data->len = len;
95 LOCAL VOID datcache_data_delete(datcache_data_t *cache_data)
97 QueRemove(&(cache_data->queue));
98 if (cache_data->data != NULL) {
99 free(cache_data->data);
104 EXPORT W datcache_appenddata(datcache_t *cache, UB *data, W len)
106 datcache_data_t *cache_data;
109 err = wai_sem(cache->semid, T_FOREVER);
114 if (cache->context != NULL) {
115 sig_sem(cache->semid);
119 cache_data = datcache_data_new(data, len);
120 if (cache_data == NULL) {
121 sig_sem(cache->semid);
122 return -1; /* TODO */
124 QueInsert(&(cache_data->queue), &(cache->datalist.queue));
125 cache->s_datsize += len;
127 sig_sem(cache->semid);
131 EXPORT VOID datcache_cleardata(datcache_t *cache)
133 datcache_data_t *cache_data;
137 err = wai_sem(cache->semid, T_FOREVER);
142 if (cache->context != NULL) {
143 sig_sem(cache->semid);
148 ok = isQueEmpty(&(cache->datalist.queue));
152 cache_data = (datcache_data_t*)cache->datalist.queue.next;
153 datcache_data_delete(cache_data);
155 free(cache->datalist.data);
157 cache->datalist.data = NULL;
158 cache->datalist.len = 0;
159 cache->s_datsize = 0;
161 sig_sem(cache->semid);
164 EXPORT Bool datcache_datareadcontext_nextdata(datcache_datareadcontext_t *context, UB **bin, W *len)
166 datcache_data_t *next;
168 if (context->current == NULL) {
172 *bin = context->current->data + context->index;
173 *len = context->current->len - context->index;
175 next = datcache_data_next(context->current);
176 if (next == &(context->datcache->datalist)) {
179 context->current = next;
185 LOCAL datcache_datareadcontext_t* datcache_datareadcontext_new(datcache_t *cache)
187 datcache_datareadcontext_t *context;
189 context = malloc(sizeof(datcache_datareadcontext_t*));
190 if (context == NULL) {
193 context->datcache = cache;
198 LOCAL VOID datcache_datareadcontext_delete(datcache_datareadcontext_t *context)
203 EXPORT datcache_datareadcontext_t* datcache_startdataread(datcache_t *cache, W start)
205 datcache_datareadcontext_t *context;
206 datcache_data_t *cache_data;
209 err = wai_sem(cache->semid, T_FOREVER);
214 if (cache->context != NULL) {
215 sig_sem(cache->semid);
219 context = datcache_datareadcontext_new(cache);
220 if (context == NULL) {
223 cache->context = context;
225 if (start >= cache->s_datsize) {
226 context->current = NULL;
231 cache_data = &(cache->datalist);
234 if (dest < cache_data->len) {
237 dest -= cache_data->len;
238 cache_data = datcache_data_next(cache_data);
241 context->current = cache_data;
242 context->index = dest;
247 EXPORT VOID datcache_enddataread(datcache_t *cache, datcache_datareadcontext_t *context)
249 cache->context = NULL;
250 datcache_datareadcontext_delete(context);
252 sig_sem(cache->semid);
255 EXPORT VOID datcache_getlatestheader(datcache_t *cache, UB **header, W *len)
257 *header = cache->latestheader;
258 *len = cache->latestheader_len;
261 EXPORT W datcache_updatelatestheader(datcache_t *cache, UB *header, W len)
265 latestheader0 = realloc(cache->latestheader, len + 1);
266 if (latestheader0 == NULL) {
270 cache->latestheader = latestheader0;
271 memcpy(cache->latestheader, header, len);
272 cache->latestheader_len = len;
273 cache->latestheader[cache->latestheader_len] = '\0';
278 EXPORT VOID datcache_gethost(datcache_t *cache, UB **host, W *len)
281 *len = cache->host_len;
284 EXPORT VOID datcache_getborad(datcache_t *cache, UB **borad, W *len)
286 *borad = cache->board;
287 *len = cache->board_len;
290 EXPORT VOID datcache_getthread(datcache_t *cache, UB **thread, W *len)
292 *thread = cache->thread;
293 *len = cache->thread_len;
296 LOCAL VOID datcache_setupretrinfo(datcache_t *cache, UB *retrinfo, W len)
300 cache->retrinfo = retrinfo;
301 cache->retrinfo_len = len;
305 cache->board_len = 0;
306 cache->thread = NULL;
307 cache->thread_len = 0;
309 if (cache->retrinfo == NULL) {
313 cache->host = cache->retrinfo;
314 for (; i < len; i++) {
315 if (cache->retrinfo[i] == '\n') {
322 cache->board = cache->retrinfo + i;
323 for (; i < len; i++) {
324 if (cache->retrinfo[i] == '\n') {
331 cache->thread = cache->retrinfo + i;
332 for (; i < len; i++) {
333 if (cache->retrinfo[i] == '\n') {
340 LOCAL W datcache_preparerec_forwritefile(W fd, W rectype, W subtype)
344 err = fnd_rec(fd, F_TOPEND, 1 << rectype, subtype, NULL);
346 err = ins_rec(fd, NULL, 0, rectype, subtype, 0);
350 err = see_rec(fd, -1, 0, NULL);
354 } else if (err < 0) {
355 return -1; /* TODO */
357 err = trc_rec(fd, 0);
366 EXPORT W datcache_datasize(datcache_t *cache)
368 return cache->s_datsize;
371 EXPORT W datcache_writefile(datcache_t *cache)
374 datcache_data_t *cache_data;
376 /* TODO: blush up implementation for speed up. */
377 if (cache->s_datsize > 0) {
378 err = datcache_preparerec_forwritefile(cache->fd, DATCACHE_RECORDTYPE_MAIN, 0);
382 cache_data = &(cache->datalist);
384 err = wri_rec(cache->fd, -1, cache_data->data, cache_data->len, NULL, NULL, 0);
388 cache_data = datcache_data_next(cache_data);
389 if (cache_data == &(cache->datalist)) {
395 if (cache->latestheader_len > 0) {
396 err = datcache_preparerec_forwritefile(cache->fd, DATCACHE_RECORDTYPE_INFO, DATCACHE_RECORDSUBTYPE_HEADER);
400 err = wri_rec(cache->fd, -1, cache->latestheader, cache->latestheader_len, NULL, NULL, 0);
409 EXPORT W datcache_addresiddata(datcache_t *cache, TC *idstr, W idstr_len, UW attr, COLOR color)
411 return residhash_adddata(&cache->residhash, idstr, idstr_len, attr, color);
414 EXPORT W datcache_searchresiddata(datcache_t *cache, TC *idstr, W idstr_len, UW *attr, COLOR *color)
416 return residhash_searchdata(&cache->residhash, idstr, idstr_len, attr, color);
419 EXPORT VOID datcache_removeresiddata(datcache_t *cache, TC *idstr, W idstr_len)
421 residhash_removedata(&cache->residhash, idstr, idstr_len);
424 LOCAL W datcache_getrec_fromfile(W fd, W rectype, W subtype, UB **data, W *size)
429 err = fnd_rec(fd, F_TOPEND, 1 << rectype, subtype, NULL);
436 return -1; /* TODO */
438 err = rea_rec(fd, 0, NULL, 0, &size0, NULL);
440 return -1; /* TODO */
447 data0 = malloc(size0);
449 return -1; /* TODO */
451 err = rea_rec(fd, 0, data0, size0, NULL, NULL);
454 return -1; /* TODO */
463 LOCAL W datcache_getdat_fromfile(W fd, UB **data, W *size)
465 return datcache_getrec_fromfile(fd, DATCACHE_RECORDTYPE_MAIN, 0, data, size);
468 LOCAL W datcache_getretrinfo_fromfile(W fd, UB **data, W *size)
470 return datcache_getrec_fromfile(fd, DATCACHE_RECORDTYPE_INFO, DATCACHE_RECORDSUBTYPE_RETRIEVE, data, size);
473 LOCAL W datcache_getheader_fromfile(W fd, UB **data, W *size)
475 return datcache_getrec_fromfile(fd, DATCACHE_RECORDTYPE_INFO, DATCACHE_RECORDSUBTYPE_HEADER, data, size);
478 EXPORT datcache_t* datcache_new(VID vid)
483 W size, retrinfo_len, header_len;
484 UB *rawdat, *retrinfo, *header;
486 fd = oopn_obj(vid, NULL, F_READ|F_WRITE, NULL);
490 semid = cre_sem(1, SEM_EXCL|DELEXIT);
495 err = datcache_getdat_fromfile(fd, &rawdat, &size);
501 err = datcache_getretrinfo_fromfile(fd, &retrinfo, &retrinfo_len);
503 if (rawdat != NULL) {
510 err = datcache_getheader_fromfile(fd, &header, &header_len);
512 if (retrinfo != NULL) {
515 if (rawdat != NULL) {
523 cache = (datcache_t*)malloc(sizeof(datcache_t));
532 cache->semid = semid;
533 QueInit(&(cache->datalist.queue));
534 cache->datalist.data = rawdat;
535 cache->datalist.len = size;
536 cache->s_datsize = size;
537 cache->context = NULL;
539 datcache_setupretrinfo(cache, retrinfo, retrinfo_len);
540 cache->latestheader = header;
541 cache->latestheader_len = header_len;
543 err = residhash_initialize(&cache->residhash);
556 EXPORT VOID datcache_delete(datcache_t *cache)
558 datcache_data_t *cache_data;
561 residhash_finalize(&cache->residhash);
563 if (cache->latestheader != NULL) {
564 free(cache->latestheader);
566 if (cache->retrinfo != NULL) {
567 free(cache->retrinfo);
571 ok = isQueEmpty(&(cache->datalist.queue));
575 cache_data = datcache_data_next(&cache->datalist);
576 datcache_data_delete(cache_data);
578 free(cache->datalist.data);
579 del_sem(cache->semid);