/* After parsing, but before sending to various devices. Will repeat 3 times if needed */ SIZE_OR_ERROR FS_read_postparse(struct one_wire_query *owq) { struct parsedname *pn = PN(owq); SIZE_OR_ERROR read_or_error; // ServerRead jumps in here, perhaps with non-file entry if (pn->selected_device == NO_DEVICE || pn->selected_filetype == NO_FILETYPE) { return -EISDIR; } /* Normal read. Try three times */ LEVEL_DEBUG("%s", pn->path); STATLOCK; AVERAGE_IN(&read_avg); AVERAGE_IN(&all_avg); STATUNLOCK; /* First try */ STAT_ADD1(read_tries[0]); read_or_error = (pn->type == ePN_real) ? FS_read_real(owq) : FS_r_virtual(owq); STATLOCK; if (read_or_error >= 0) { ++read_success; /* statistics */ read_bytes += read_or_error; /* statistics */ } AVERAGE_OUT(&read_avg); AVERAGE_OUT(&all_avg); STATUNLOCK; LEVEL_DEBUG("%s return %d", pn->path, read_or_error); return read_or_error; }
/* After parsing, choose special read based on path type */ static SIZE_OR_ERROR FS_read_distribute(struct one_wire_query *owq) { // Device not locked SIZE_OR_ERROR read_or_error = 0; LEVEL_DEBUG("%s", PN(owq)->path); STATLOCK; AVERAGE_IN(&read_avg); AVERAGE_IN(&all_avg); STATUNLOCK; /* handle DeviceSimultaneous */ if (PN(owq)->selected_device == DeviceSimultaneous) { read_or_error = FS_r_simultaneous(owq); } else { read_or_error = FS_r_given_bus(owq); } STATLOCK; if (read_or_error >= 0) { ++read_success; /* statistics */ read_bytes += read_or_error; /* statistics */ } AVERAGE_OUT(&read_avg); AVERAGE_OUT(&all_avg); STATUNLOCK; LEVEL_DEBUG("%s returns %d", PN(owq)->path, read_or_error); //printf("FS_read_distribute: pid=%ld return %d\n", pthread_self(), read_or_error); return read_or_error; }
/* return size if ok, else negative */ SIZE_OR_ERROR FS_write_postparse(struct one_wire_query *owq) { ZERO_OR_ERROR write_or_error; struct parsedname *pn = PN(owq); if (Globals.readonly) { LEVEL_DEBUG("Attempt to write but readonly set on command line."); return -EROFS; // read-only invokation } if (IsDir(pn)) { LEVEL_DEBUG("Attempt to write to a directory."); return -EISDIR; // not a file } STATLOCK; AVERAGE_IN(&write_avg); AVERAGE_IN(&all_avg); ++write_calls; /* statistics */ STATUNLOCK; write_or_error = FS_write_post_stats( owq ) ; STATLOCK; // write_or_error is still ZERO_OR_ERROR mode if ( write_or_error == 0 ) { LEVEL_DEBUG("Successful write to %s",pn->path) ; } else { LEVEL_DEBUG("Error writing to %s",pn->path) ; } if (write_or_error == 0) { ++write_success; /* statistics */ write_bytes += OWQ_size(owq); /* statistics */ // write_or_error now SIZE_OR_ERROR mode write_or_error = OWQ_size(owq); /* here's where the size is used! */ } AVERAGE_OUT(&write_avg); AVERAGE_OUT(&all_avg); STATUNLOCK; return write_or_error; }
/* After parsing, but before sending to various devices. Will repeat 3 times if needed */ SIZE_OR_ERROR FS_read_postparse(struct one_wire_query *owq) { struct parsedname *pn = PN(owq); SIZE_OR_ERROR read_or_error; /* Normal read. Try three times */ LEVEL_DEBUG("%s", pn->path); STATLOCK; AVERAGE_IN(&read_avg); AVERAGE_IN(&all_avg); STATUNLOCK; /* First try */ STAT_ADD1(read_tries[0]); /* Check file type. */ if (pn->selected_device == NO_DEVICE || pn->selected_filetype == NO_FILETYPE) { if (KnownBus(pn) && BusIsServer(pn->selected_connection)) { /* Pass unknown remote filetype to remote owserver. */ read_or_error = FS_r_given_bus(owq); } else { /* Local unknown filetypes are directories. */ return -EISDIR; } } else { /* Local known filetypes are handled here. */ read_or_error = (pn->type == ePN_real) ? FS_read_real(owq) : FS_r_virtual(owq); } STATLOCK; if (read_or_error >= 0) { ++read_success; /* statistics */ read_bytes += read_or_error; /* statistics */ } AVERAGE_OUT(&read_avg); AVERAGE_OUT(&all_avg); STATUNLOCK; LEVEL_DEBUG("%s return %d", pn->path, read_or_error); return read_or_error; }
/* return 0 if good, 1 if not */ static GOOD_OR_BAD Cache_Add_Common(struct tree_node *tn) { struct tree_opaque *opaque; enum { no_add, yes_add, just_update } state = no_add; node_show(tn); LEVEL_DEBUG("Add to cache sn " SNformat " pointer=%p index=%d size=%d", SNvar(tn->tk.sn), tn->tk.p, tn->tk.extension, tn->dsize); CACHE_WLOCK; if (cache.time_to_kill < NOW_TIME) { // old database has timed out FlipTree() ; } if (Globals.cache_size && (cache.old_ram_size + cache.new_ram_size > Globals.cache_size)) { // failed size test owfree(tn); } else if ((opaque = tsearch(tn, &cache.temporary_tree_new, tree_compare))) { //printf("Cache_Add_Common to %p\n",opaque); if (tn != opaque->key) { cache.new_ram_size += sizeof(tn) - sizeof(opaque->key); owfree(opaque->key); opaque->key = tn; state = just_update; } else { state = yes_add; cache.new_ram_size += sizeof(tn); } } else { // nothing found or added?!? free our memory segment owfree(tn); } CACHE_WUNLOCK; /* Added or updated, update statistics */ switch (state) { case yes_add: // add new entry STATLOCK; AVERAGE_IN(&new_avg); ++cache_adds; /* statistics */ STATUNLOCK; return gbGOOD; case just_update: // update the time mark and data STATLOCK; AVERAGE_MARK(&new_avg); ++cache_adds; /* statistics */ STATUNLOCK; return gbGOOD; default: // unable to add return gbBAD; } }
/* return 0 if good, 1 if not */ static GOOD_OR_BAD Cache_Add_Persistent(struct tree_node *tn) { struct tree_opaque *opaque; enum { no_add, yes_add, just_update } state = no_add; LEVEL_DEBUG("Adding data to permanent store"); PERSISTENT_WLOCK; opaque = tsearch(tn, &cache.persistent_tree, tree_compare) ; if ( opaque != NULL ) { //printf("CACHE ADD pointer=%p, key=%p\n",tn,opaque->key); if (tn != opaque->key) { owfree(opaque->key); opaque->key = tn; state = just_update; } else { state = yes_add; } } else { // nothing found or added?!? free our memory segment owfree(tn); } PERSISTENT_WUNLOCK; switch (state) { case yes_add: STATLOCK; AVERAGE_IN(&store_avg); STATUNLOCK; return gbGOOD; case just_update: STATLOCK; AVERAGE_MARK(&store_avg); STATUNLOCK; return gbGOOD; default: return gbBAD; } }