/* Choose in order: * (first) 0x81 * (first) 0x01 * first other family * 0x00 * */ GOOD_OR_BAD DS9490_ID_this_master(struct connection_in *in) { struct dirblob db ; BYTE sn[SERIAL_NUMBER_SIZE] ; int device_number ; RETURN_BAD_IF_BAD( DS9490_root_dir( &db, in ) ) ; // Use 0x00 if no devices (homegrown adapters?) if ( DirblobElements( &db) == 0 ) { DirblobClear( &db ) ; memset( in->master.usb.ds1420_address, 0, SERIAL_NUMBER_SIZE ) ; LEVEL_DEFAULT("Set DS9490 %s unique id 0x00 (no devices at all)", SAFESTRING(DEVICENAME(in))) ; return gbGOOD ; } // look for the special 0x81 device device_number = 0 ; while ( DirblobGet( device_number, sn, &db ) == 0 ) { if (sn[0] == 0x81) { // 0x81 family code memcpy(in->master.usb.ds1420_address, sn, SERIAL_NUMBER_SIZE); LEVEL_DEFAULT("Set DS9490 %s unique id to " SNformat, SAFESTRING(DEVICENAME(in)), SNvar(in->master.usb.ds1420_address)); DirblobClear( &db ) ; return gbGOOD ; } ++device_number ; } // look for the (less specific, for older DS9490s) 0x01 device device_number = 0 ; while ( DirblobGet( device_number, sn, &db ) == 0 ) { if (sn[0] == 0x01) { // 0x01 family code memcpy(in->master.usb.ds1420_address, sn, SERIAL_NUMBER_SIZE); LEVEL_DEFAULT("Set DS9490 %s unique id to " SNformat, SAFESTRING(DEVICENAME(in)), SNvar(in->master.usb.ds1420_address)); DirblobClear( &db ) ; return gbGOOD ; } ++device_number ; } // Take the first device, whatever it is DirblobGet( 0, sn, &db ) ; memcpy(in->master.usb.ds1420_address, sn, SERIAL_NUMBER_SIZE); LEVEL_DEFAULT("Set DS9490 %s unique id to " SNformat, SAFESTRING(DEVICENAME(in)), SNvar(in->master.usb.ds1420_address)); DirblobClear( &db ) ; return gbGOOD; }
/* return 0 if good, 1 if not */ GOOD_OR_BAD Cache_Add_Device(const int bus_nr, const BYTE * sn) { time_t duration = TimeOut(fc_presence); struct tree_node *tn; if (duration <= 0) { return gbGOOD; /* in case timeout set to 0 */ } if ( sn[0] == 0 ) { //bad serial number return gbGOOD ; } tn = (struct tree_node *) owmalloc(sizeof(struct tree_node) + sizeof(int)); if (!tn) { return gbBAD; } LEVEL_DEBUG("Adding device location " SNformat " bus=%d", SNvar(sn), (int) bus_nr); LoadTK(sn, Device_Marker, 0, tn ); tn->expires = duration + NOW_TIME; tn->dsize = sizeof(int); memcpy(TREE_DATA(tn), &bus_nr, sizeof(int)); return Add_Stat(&cache_dev, Cache_Add_Common(tn)); }
/* Look in caches, 0=found and valid, 1=not or uncachable in the first place */ GOOD_OR_BAD Cache_Get(void *data, size_t * dsize, const struct parsedname *pn) { time_t duration; struct tree_node tn; int persistent ; // do check here to avoid needless processing if (IsUncachedDir(pn) || IsAlarmDir(pn)) { return gbBAD; } // Special handling of Mock persistent = IsThisPersistent(pn) ; if ( persistent ) { duration = 1 ; } else { duration = TimeOut(pn->selected_filetype->change); if (duration <= 0) { return gbBAD; /* in case timeout set to 0 */ } } LEVEL_DEBUG(SNformat " size=%d IsUncachedDir=%d", SNvar(pn->sn), (int) dsize[0], IsUncachedDir(pn)); LoadTK( pn->sn, pn->selected_filetype, pn->extension, &tn ); return persistent ? Get_Stat(&cache_pst, Cache_Get_Persistent(data, dsize, &duration, &tn)) : Get_Stat(&cache_ext, Cache_Get_Common(data, dsize, &duration, &tn)); }
/* Test for a simultaneous property If the property isn't independently cached, return false (1) If the simultaneous conversion is more recent, return false (1) Else return the cached value and true (0) */ GOOD_OR_BAD Cache_Get_Simul_Time(enum simul_type type, time_t * dwell_time, const struct parsedname * pn) { // valid cached primary data -- see if a simultaneous conversion should be used instead struct tree_node tn; time_t duration ; time_t time_left ; size_t dsize_simul = 0 ; struct parsedname pn_directory ; duration = TimeOut(ipSimul[type].change); // time allocated this conversion if ( duration <= 0) { // uncachable return gbBAD; } LEVEL_DEBUG("Looking for conversion time "SNformat, SNvar(pn->sn)); FS_LoadDirectoryOnly(&pn_directory, pn); LoadTK(pn_directory.sn, Simul_Marker[type], pn->selected_connection->index, &tn ) ; if ( Get_Stat(&cache_int, Cache_Get_Common(NULL, &dsize_simul, &time_left, &tn)) ) { return gbBAD ; } // duration_simul is time left // duration is time allocated // back-compute dwell time dwell_time[0] = duration - time_left ; return gbGOOD ; }
static enum search_status DS9490_next_both(struct device_search *ds, const struct parsedname *pn) { int dir_gulp_elements = (pn->ds2409_depth==0) ? DS2490_DIR_GULP_ELEMENTS : 1 ; // LOOK FOR NEXT ELEMENT ++ds->index; LEVEL_DEBUG("Index %d", ds->index); if (ds->index % dir_gulp_elements == 0) { if (ds->LastDevice) { return search_done; } switch ( DS9490_directory(ds, pn) ) { case search_done: return search_done; case search_error: return search_error; case search_good: break; } } switch ( DirblobGet(ds->index % dir_gulp_elements, ds->sn, &(ds->gulp) ) ) { case 0: LEVEL_DEBUG("SN found: " SNformat, SNvar(ds->sn)); return search_good; case -ENODEV: default: LEVEL_DEBUG("SN finished"); return search_done; } }
// Delete a serial number's alias // Safe to call if no alias exists // Also deletes from linked alias_sn file void Cache_Del_Alias(const BYTE * sn) { ASCII * alias_name ; struct tree_node *tn; size_t size ; alias_name = Cache_Get_Alias( sn ) ; if ( alias_name == NULL ) { // doesn't exist // (or a memory error -- unlikely) return ; } LEVEL_DEBUG("Deleting alias %s from "SNformat, alias_name, SNvar(sn)) ; size = strlen( alias_name ) ; tn = (struct tree_node *) owmalloc(sizeof(struct tree_node) + size + 1 ); if ( tn != NULL ) { tn->expires = NOW_TIME; tn->dsize = size; memcpy((ASCII *)TREE_DATA(tn), alias_name, size+1); // includes NULL LoadTK( sn, Alias_Marker, 0, tn ) ; Del_Stat(&cache_pst, Cache_Del_Persistent(tn)); Cache_Del_Alias_SN( alias_name ) ; } owfree( alias_name ) ; }
/* return 0 if good, 1 if not */ GOOD_OR_BAD Cache_Add_SlaveSpecific(const void *data, const size_t datasize, const struct internal_prop *ip, const struct parsedname *pn) { struct tree_node *tn; time_t duration; //printf("Cache_Add_SlaveSpecific\n"); if (!pn) { return gbGOOD; // do check here to avoid needless processing } duration = TimeOut(ip->change); if (duration <= 0) { return gbGOOD; /* in case timeout set to 0 */ } tn = (struct tree_node *) owmalloc(sizeof(struct tree_node) + datasize); if (!tn) { return gbBAD; } LEVEL_DEBUG("Adding internal data for "SNformat " size=%d", SNvar(pn->sn), (int) datasize); LoadTK( pn->sn, ip->name, EXTENSION_INTERNAL, tn ); tn->expires = duration + NOW_TIME; tn->dsize = datasize; if (datasize) { memcpy(TREE_DATA(tn), data, datasize); } //printf("ADD INTERNAL name= %s size=%d \n",tn->tk.p.nm,tn->dsize); //printf(" ADD INTERNAL data[0]=%d size=%d \n",((BYTE *)data)[0],datasize); switch (ip->change) { case fc_persistent: return Add_Stat(&cache_pst, Cache_Add_Persistent(tn)); default: return Add_Stat(&cache_int, Cache_Add_Common(tn)); } }
static enum search_status LINK_next_both(struct device_search *ds, const struct parsedname *pn) { struct connection_in * in = pn->selected_connection ; //Special case for DS2409 hub, use low-level code if ( pn->ds2409_depth>0 ) { return search_error ; } if (ds->LastDevice) { return search_done; } if (ds->index == -1) { if ( BAD(LINK_directory(ds, in)) ) { return search_error; } } // LOOK FOR NEXT ELEMENT ++ds->index; LEVEL_DEBUG("Index %d", ds->index); switch ( DirblobGet(ds->index, ds->sn, &(ds->gulp) ) ) { case 0: LEVEL_DEBUG("SN found: " SNformat "", SNvar(ds->sn)); return search_good; case -ENODEV: default: ds->LastDevice = 1; LEVEL_DEBUG("SN finished"); return search_done; } }
// Look on a given connection for the device static INDEX_OR_ERROR CheckThisConnection(int bus_nr, struct parsedname *pn) { struct parsedname s_pn_copy; struct parsedname * pn_copy = &s_pn_copy ; struct connection_in * in = find_connection_in(bus_nr) ; INDEX_OR_ERROR connection_result = INDEX_BAD ; if ( in == NO_CONNECTION ) { return INDEX_BAD ; } memcpy(pn_copy, pn, sizeof(struct parsedname)); // shallow copy pn_copy->selected_connection = in; if ( BAD( TestConnection(pn_copy) ) ) { // Connection currently disconnected return INDEX_BAD; } else if (BusIsServer(in)) { // Server if ( INDEX_VALID( ServerPresence(pn_copy) ) ) { connection_result = in->index; } } else if ( in->iroutines.flags & ADAP_FLAG_sham ) { return INDEX_BAD ; } else if ( in->iroutines.flags & ADAP_FLAG_presence_from_dirblob ) { // local connection with a dirblob (like fake, mock, ...) if ( GOOD( PresenceFromDirblob( pn_copy ) ) ) { connection_result = in->index ; } } else { // local connection but need to ask directly struct transaction_log t[] = { TRXN_NVERIFY, TRXN_END, }; if ( GOOD( BUS_transaction(t, pn_copy) ) ) { connection_result = in->index ; } } if ( connection_result == INDEX_BAD ) { LEVEL_DEBUG("Presence of "SNformat" NOT found on bus %s",SNvar(pn_copy->sn),SAFESTRING(DEVICENAME(in))) ; } else { LEVEL_DEBUG("Presence of "SNformat" FOUND on bus %s",SNvar(pn_copy->sn),SAFESTRING(DEVICENAME(in))) ; Cache_Add_Device(in->index,pn_copy->sn) ; // add or update cache */ } return connection_result ; }
enum search_status BUS_first_alarm(struct device_search *ds, const struct parsedname *pn) { LEVEL_DEBUG("Start of directory path=%s device=" SNformat, SAFESTRING(pn->path), SNvar(pn->sn)); // reset the search state BUS_first_both(ds); ds->search = _1W_CONDITIONAL_SEARCH_ROM; return BUS_next(ds, pn); }
// very strange command to get out of test mode. // Uses a different 1-wire command static GOOD_OR_BAD OW_out_of_test_mode( const struct parsedname * pn ) { BYTE out_of_test[] = { 0x96, SNvar(pn->sn), 0x3C, } ; struct transaction_log t[] = { TRXN_RESET, TRXN_WRITE(out_of_test, 1 + SERIAL_NUMBER_SIZE + 1 ), TRXN_END, }; return BUS_transaction( t, pn ) ; }
/* return 0 if good, 1 if not */ GOOD_OR_BAD Cache_Add_Simul(const enum simul_type type, const struct parsedname *pn) { // Note: pn already points to directory time_t duration = TimeOut(fc_volatile); struct tree_node *tn; if (pn==NO_PARSEDNAME || pn->selected_connection==NO_CONNECTION) { return gbGOOD; // do check here to avoid needless processing } switch ( get_busmode(pn->selected_connection) ) { case bus_fake: case bus_tester: case bus_mock: case bus_bad: case bus_unknown: return gbGOOD ; default: break ; } if (duration <= 0) { return gbGOOD; /* in case timeout set to 0 */ } // allocate space for the node and data LEVEL_DEBUG("Adding for conversion time for "SNformat, SNvar(pn->sn)); tn = (struct tree_node *) owmalloc(sizeof(struct tree_node)); if (!tn) { return gbBAD; } LEVEL_DEBUG(SNformat, SNvar(pn->sn)); // populate node with directory name and dirblob LoadTK( pn->sn, Simul_Marker[type], pn->selected_connection->index, tn) ; LEVEL_DEBUG("Simultaneous add type=%d",type); tn->expires = duration + NOW_TIME; tn->dsize = 0; return Add_Stat(&cache_dir, Cache_Add_Common(tn)); }
/* Run it as twalk(dababase, tree_show ) */ static void node_show(struct tree_node *tn) { int i; char b[26]; ctime_r(&tn->expires, b); fprintf(stderr,"\tNode " SNformat " pointer=%p extension=%d length=%d start=%p expires=%s", SNvar(tn->tk.sn), tn->tk.p, tn->tk.extension, tn->dsize, tn, b ? b : "null\n"); for (i = 0; i < sizeof(struct tree_key); ++i) { fprintf(stderr,"%.2X ", ((uint8_t *) tn)[i]); } fprintf(stderr,"\n"); }
/* return 0 if good, 1 if not */ GOOD_OR_BAD Cache_Add_Dir(const struct dirblob *db, const struct parsedname *pn) { time_t duration = TimeOut(fc_directory); struct tree_node *tn; size_t size = DirblobElements(db) * SERIAL_NUMBER_SIZE; struct parsedname pn_directory; if (pn==NO_PARSEDNAME || pn->selected_connection==NO_CONNECTION) { return gbGOOD; // do check here to avoid needless processing } switch ( get_busmode(pn->selected_connection) ) { case bus_fake: case bus_tester: case bus_mock: case bus_w1: case bus_bad: case bus_unknown: return gbGOOD ; default: break ; } if (duration <= 0) { return 0; /* in case timeout set to 0 */ } if ( DirblobElements(db) < 1 ) { // only cache long directories. // zero (or one?) entry is possibly an error and needs to be repeated more quickly LEVEL_DEBUG("Won\'t cache empty directory"); Cache_Del_Dir( pn ) ; return gbGOOD ; } // allocate space for the node and data tn = (struct tree_node *) owmalloc(sizeof(struct tree_node) + size); if (!tn) { return gbBAD; } LEVEL_DEBUG("Adding directory for " SNformat " elements=%d", SNvar(pn->sn), DirblobElements(db)); // populate node with directory name and dirblob FS_LoadDirectoryOnly(&pn_directory, pn); LoadTK( pn_directory.sn, Directory_Marker, pn->selected_connection->index, tn ); tn->expires = duration + NOW_TIME; tn->dsize = size; if (size) { memcpy(TREE_DATA(tn), db->snlist, size); } return Add_Stat(&cache_dir, Cache_Add_Common(tn)); }
/* Look in caches, 0=found and valid, 1=not or uncachable in the first place */ GOOD_OR_BAD Cache_Get_Device(void *bus_nr, const struct parsedname *pn) { time_t duration = TimeOut(fc_presence); size_t size = sizeof(int); struct tree_node tn; if (duration <= 0) { return gbBAD; } LEVEL_DEBUG("Looking for device "SNformat, SNvar(pn->sn)); LoadTK( pn->sn, Device_Marker, 0, &tn ) ; return Get_Stat(&cache_dev, Cache_Get_Common(bus_nr, &size, &duration, &tn)); }
/* Look in caches, 0=found and valid, 1=not or uncachable in the first place */ GOOD_OR_BAD Cache_Get_Dir(struct dirblob *db, const struct parsedname *pn) { time_t duration = TimeOut(fc_directory); struct tree_node tn; struct parsedname pn_directory; DirblobInit(db); if (duration <= 0) { return gbBAD; } LEVEL_DEBUG("Looking for directory "SNformat, SNvar(pn->sn)); FS_LoadDirectoryOnly(&pn_directory, pn); LoadTK( pn_directory.sn, Directory_Marker, pn->selected_connection->index, &tn) ; return Get_Stat(&cache_dir, Cache_Get_Common_Dir(db, &duration, &tn)); }
/* duration is time left */ static enum cache_task_return Cache_Get_Common(void *data, size_t * dsize, time_t * duration, const struct tree_node *tn) { enum cache_task_return ctr_ret; time_t now = NOW_TIME; struct tree_opaque *opaque; LEVEL_DEBUG("Search in cache sn " SNformat " pointer=%p index=%d size=%d", SNvar(tn->tk.sn), tn->tk.p, tn->tk.extension, (int) dsize[0]); //node_show(tn); //new_tree(); CACHE_RLOCK; opaque = tfind(tn, &cache.temporary_tree_new, tree_compare) ; if ( opaque == NULL ) { // not found in new tree if ( cache.time_retired + duration[0] > now ) { // retired time isn't too old for this data item opaque = tfind(tn, &cache.temporary_tree_old, tree_compare) ; } } if ( opaque != NULL ) { // modify duration to time left (can be negative if expired) duration[0] = opaque->key->expires - now ; if (duration[0] > 0) { LEVEL_DEBUG("Value found in cache. Remaining life: %d seconds.",duration[0]); // Compared with >= before, but fc_second(1) always cache for 2 seconds in that case. // Very noticable when reading time-data like "/26.80A742000000/date" for example. if ( dsize[0] >= opaque->key->dsize) { // lower data size if stored value is shorter dsize[0] = opaque->key->dsize; //tree_show(opaque,leaf,0); if (dsize[0] > 0) { memcpy(data, TREE_DATA(opaque->key), dsize[0]); } ctr_ret = ctr_ok; //twalk(cache.temporary_tree_new,tree_show) ; } else { ctr_ret = ctr_size_mismatch; } } else { LEVEL_DEBUG("Value found in cache, but expired by %d seconds.",-duration[0]); ctr_ret = ctr_expired; } } else { LEVEL_DEBUG("Value not found in cache"); ctr_ret = ctr_not_found; } CACHE_RUNLOCK; return ctr_ret; }
static SEQ_OR_ERROR w1_send_touch( const BYTE * data, size_t size, const struct parsedname *pn ) { struct w1_netlink_msg w1m; struct w1_netlink_cmd w1c; memset(&w1m, 0, W1_W1M_LENGTH); w1m.type = W1_MASTER_CMD; w1m.id.mst.id = pn->selected_connection->master.w1.id ; memset(&w1c, 0, W1_W1C_LENGTH); w1c.cmd = W1_CMD_TOUCH ; w1c.len = size ; LEVEL_DEBUG("Sending w1 send/receive data message for "SNformat,SNvar(pn->sn)); return W1_send_msg( pn->selected_connection, &w1m, &w1c, data ); }
static SEQ_OR_ERROR w1_send_selecttouch( const BYTE * data, size_t size, const struct parsedname *pn ) { struct w1_netlink_msg w1m; struct w1_netlink_cmd w1c; memset(&w1m, 0, W1_W1M_LENGTH); w1m.type = W1_SLAVE_CMD; memcpy( w1m.id.id, pn->sn, 8) ; memset(&w1c, 0, W1_W1C_LENGTH); w1c.cmd = W1_CMD_TOUCH ; w1c.len = size ; LEVEL_DEBUG("Sending w1 select message for "SNformat,SNvar(pn->sn)); return W1_send_msg( pn->selected_connection, &w1m, &w1c, data ); }
/* 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; } }
/** The BUS_next function does a general search. This function continues from the previous search state (held in struct device_search). The search state can be reset by using the BUS_first function. Returns: 0=No problems, 1=Problems Sets LastDevice=1 if no more */ enum search_status BUS_next(struct device_search *ds, const struct parsedname *pn) { switch ( BUS_next_3try(ds, pn) ) { case search_good: // found a device in a directory search, add to "presence" cache LEVEL_DEBUG("Device found: " SNformat, SNvar(ds->sn)); Cache_Add_Device(pn->selected_connection->index,ds->sn) ; return search_good ; case search_done: BUS_next_cleanup(ds); return search_done; case search_error: default: BUS_next_cleanup(ds); return search_error; } }
/* look in persistent alias->sn tree */ static enum cache_task_return Cache_Get_Alias_Persistent( BYTE * sn, struct alias_tree_node * atn) { struct tree_opaque *opaque; GOOD_OR_BAD ret = gbBAD ; PERSISTENT_RLOCK; opaque = tfind(atn, &cache.persistent_alias_tree, alias_tree_compare) ; if ( opaque != NULL ) { memcpy( sn, ((struct alias_tree_node *)(opaque->key))->sn, SERIAL_NUMBER_SIZE ) ; LEVEL_DEBUG("Lookup of %s gives "SNformat, CONST_ALIAS_TREE_DATA(atn), SNvar(sn) ) ; ret = gbGOOD ; } else { LEVEL_DEBUG("Lookup of %s unsuccessful",CONST_ALIAS_TREE_DATA(atn)) ; } PERSISTENT_RUNLOCK; owfree(atn) ; return ret; }
INDEX_OR_ERROR RemoteAlias(struct parsedname *pn) { struct port_in * pin ; for ( pin = Inbound_Control.head_port ; pin ; pin = pin->first ) { struct connection_in * cin ; for ( cin=NextServer(pin->first) ; cin ; cin=NextServer(cin->next) ) { BYTE sn[SERIAL_NUMBER_SIZE] ; INDEX_OR_ERROR bus_nr = ServerAlias( sn, cin, pn ) ; if ( INDEX_VALID(bus_nr) ) { memcpy( pn->sn, sn, SERIAL_NUMBER_SIZE ) ; LEVEL_DEBUG("Remote alias for %s bus=%d "SNformat,pn->path_to_server,bus_nr,SNvar(sn)); return bus_nr ; } } } return INDEX_BAD; // no success }
/* Look in caches, 0=found and valid, 1=not or uncachable in the first place */ static enum cache_task_return Cache_Get_Common_Dir(struct dirblob *db, time_t * duration, const struct tree_node *tn) { enum cache_task_return ctr_ret; time_t now = NOW_TIME; size_t size; struct tree_opaque *opaque; LEVEL_DEBUG("Get from cache sn " SNformat " pointer=%p extension=%d", SNvar(tn->tk.sn), tn->tk.p, tn->tk.extension); CACHE_RLOCK; opaque = tfind(tn, &cache.temporary_tree_new, tree_compare) ; if ( opaque == NULL ) { // not found in new tree if ( cache.time_retired + duration[0] > now ) { // old tree could be new enough opaque = tfind(tn, &cache.temporary_tree_old, tree_compare) ; } } if ( opaque != NULL ) { duration[0] = opaque->key->expires - now ; if (duration[0] >= 0) { LEVEL_DEBUG("Dir found in cache"); size = opaque->key->dsize; if (DirblobRecreate(TREE_DATA(opaque->key), size, db) == 0) { //printf("Cache: snlist=%p, devices=%lu, size=%lu\n",*snlist,devices[0],size) ; ctr_ret = ctr_ok; } else { ctr_ret = ctr_size_mismatch; } } else { //char b[26]; //printf("GOT DEAD now:%s",ctime_r(&now,b)) ; //printf(" then:%s",ctime_r(&opaque->key->expires,b)) ; LEVEL_DEBUG("Dir expired in cache"); ctr_ret = ctr_expired; } } else { LEVEL_DEBUG("Dir not found in cache"); ctr_ret = ctr_not_found; } CACHE_RUNLOCK; return ctr_ret; }
/* returns null-terminated string */ ASCII * Cache_Get_Alias(const BYTE * sn) { struct tree_node tn; struct tree_opaque *opaque; ASCII * alias_name = NULL ; LoadTK(sn, Alias_Marker, 0, &tn ) ; PERSISTENT_RLOCK; opaque = tfind(&tn, &cache.persistent_tree, tree_compare) ; if ( opaque != NULL ) { alias_name = owmalloc( opaque->key->dsize + 1 ) ; if ( alias_name != NULL ) { memcpy( alias_name, (ASCII *)TREE_DATA(opaque->key), opaque->key->dsize+1 ) ; LEVEL_DEBUG("Retrieving " SNformat " alias=%s", SNvar(sn), alias_name ); } } PERSISTENT_RUNLOCK; return alias_name ; }
/* return 0 if good, 1 if not */ static GOOD_OR_BAD Cache_Add(const void *data, const size_t datasize, const struct parsedname *pn) { struct tree_node *tn; time_t duration; int persistent ; if (!pn || IsAlarmDir(pn)) { return gbGOOD; // do check here to avoid needless processing } // Special handling of Mock persistent = IsThisPersistent(pn) ; if ( persistent ) { duration = 1 ; } else { duration = TimeOut(pn->selected_filetype->change); if (duration <= 0) { return gbGOOD; /* in case timeout set to 0 */ } } // allocate space for the node and data tn = (struct tree_node *) owmalloc(sizeof(struct tree_node) + datasize); if (!tn) { return gbBAD; } LEVEL_DEBUG(SNformat " size=%d", SNvar(pn->sn), (int) datasize); // populate the node structure with data LoadTK( pn->sn, pn->selected_filetype, pn->extension, tn ); tn->expires = duration + NOW_TIME; tn->dsize = datasize; if (datasize) { memcpy(TREE_DATA(tn), data, datasize); } return persistent ? Add_Stat(&cache_pst, Cache_Add_Persistent(tn)) : Add_Stat(&cache_ext, Cache_Add_Common(tn)) ; }
/* return 0 if good, 1 if not */ GOOD_OR_BAD Cache_Add_Alias(const ASCII *name, const BYTE * sn) { struct tree_node *tn; size_t size = strlen(name) ; if ( size == 0 ) { return gbGOOD ; } tn = (struct tree_node *) owmalloc(sizeof(struct tree_node) + size + 1 ); if (!tn) { return gbBAD; } LEVEL_DEBUG("Adding alias for " SNformat " = %s", SNvar(sn), name); LoadTK( sn, Alias_Marker, 0, tn ); tn->expires = NOW_TIME; tn->dsize = size; memcpy((ASCII *)TREE_DATA(tn), name, size+1 ); // includes NULL Cache_Add_Alias_SN( name, sn ) ; return Add_Stat(&cache_pst, Cache_Add_Persistent(tn)); }
INDEX_OR_ERROR RemoteAlias(struct parsedname *pn) { struct remotealias_struct ras ; ras.pin = Inbound_Control.head_port ; ras.pn = pn ; ras.bus_nr = INDEX_BAD ; memset( ras.sn, 0, SERIAL_NUMBER_SIZE) ; if ( ras.pin != NULL ) { RemoteAlias_callback_port( (void *) (&ras) ) ; } memcpy( pn->sn, ras.sn, SERIAL_NUMBER_SIZE ) ; if ( INDEX_VALID( ras.bus_nr ) ) { LEVEL_DEBUG("Remote alias for %s bus=%d "SNformat,pn->path_to_server,ras.bus_nr,SNvar(ras.sn)); } else { LEVEL_DEBUG("Remote alias for %s not found",pn->path_to_server); } return ras.bus_nr; }
/* Look in caches, 0=found and valid, 1=not or uncachable in the first place */ static GOOD_OR_BAD Cache_Get_Internal(void *data, size_t * dsize, const struct internal_prop *ip, const struct parsedname *pn) { struct tree_node tn; time_t duration; //printf("Cache_Get_Internal"); if (!pn) { return gbBAD; // do check here to avoid needless processing } duration = TimeOut(ip->change); if (duration <= 0) { return gbBAD; /* in case timeout set to 0 */ } LEVEL_DEBUG(SNformat " size=%d", SNvar(pn->sn), (int) dsize[0]); LoadTK( pn->sn, ip->name, EXTENSION_INTERNAL, &tn) ; switch (ip->change) { case fc_persistent: return Get_Stat(&cache_pst, Cache_Get_Persistent(data, dsize, &duration, &tn)); default: return Get_Stat(&cache_int, Cache_Get_Common(data, dsize, &duration, &tn)); } }
static enum search_status W1_next_both(struct device_search *ds, const struct parsedname *pn) { if (ds->LastDevice) { return search_done; } if (++(ds->index) == 0) { // first pass, load the directory DirblobClear( &(ds->gulp) ); if ( W1_Process_Response( search_callback, w1_send_search(ds,pn), ds, pn ) != nrs_complete) { return search_error; } } switch ( DirblobGet(ds->index, ds->sn, &(ds->gulp) ) ) { case 0: LEVEL_DEBUG("SN found: " SNformat "", SNvar(ds->sn)); return search_good; case -ENODEV: default: ds->LastDevice = 1; LEVEL_DEBUG("SN finished"); return search_done; } }