public AttributeValue[] read_attributes_2(final String[] names, final DevSource source)
	    throws DevFailed {
	Util.out4.println("DeviceImpl.read_attributes_2 arrived src=" + source.value());

	// If the source parameter specifies device, call the read_attribute
	// method implemented by the DeviceImpl class
	if (source == DevSource.DEV) {
	    return read_attributes(names);
	}

	// final boolean att_in_fault = false;
	boolean polling_failed = false;

	// Record operation request in black box
	blackbox.insert_op(Op_Read_Attr_2);

	AttributeValue[] back = null;

	try {
	    // Build a sequence with the names of the attribute to be read.
	    // This is necessary in case of the "AllAttr" shortcut is used
	    // If all attributes are wanted, build this list
	    int i, j;
	    boolean all_attr = false;
	    final Vector poll_list = get_poll_obj_list(); // PollObj
	    final int nb_poll = poll_list.size();
	    final int nb_names = names.length;
	    String[] real_names = names;
	    // Check if All Attr
	    if (nb_names == 1) {
		final String att_name = names[0];
		if (att_name.equals(Tango_AllAttr)) {
		    all_attr = true;
		    int nb_real = 0;
		    // Get the real number
		    for (i = 0; i < nb_poll; i++) {
			final PollObj poll_obj = (PollObj) poll_list.elementAt(i);
			if (poll_obj.get_type() == Tango_POLL_ATTR) {
			    nb_real++;
			}
		    }
		    // get the real polle object
		    real_names = new String[nb_real];
		    for (i = 0, j = 0; i < nb_poll && j < nb_real; i++) {
			final PollObj poll_obj = (PollObj) poll_list.elementAt(i);
			if (poll_obj.get_type() == Tango_POLL_ATTR) {
			    real_names[j++] = poll_obj.get_name();
			}
		    }
		}
	    }

	    // Check that device supports the wanted attribute
	    if (all_attr == false) {
		for (i = 0; i < real_names.length; i++) {
		    dev_attr.get_attr_ind_by_name(real_names[i]);
		}
	    }
	    // Check that all wanted attributes are polled.
	    // If some are non polled, store
	    // their name in the real_names sequence in a vector
	    final Vector non_polled = new Vector(); // String
	    if (all_attr == false) {
		for (i = 0; i < real_names.length; i++) {
		    for (j = 0; j < nb_poll; j++) {
			final PollObj poll_obj = (PollObj) poll_list.elementAt(j);
			if (poll_obj.get_name().equals(real_names[i].toLowerCase())) {
			    break;
			}
		    }
		    if (j == nb_poll) {
			non_polled.add(real_names[i]);
		    }
		}
	    }
	    // If some attributes are not polled but their polling update period
	    // is defined,
	    // and the attribute is not in the device list of attr which should
	    // not be
	    // polled, start to poll them
	    final Vector poll_period = new Vector();
	    if (non_polled.size() != 0) {
		// Check that it is possible to start polling for the non polled
		// attribute
		for (i = 0; i < non_polled.size(); i++) {
		    final String non_polled_name = (String) non_polled.elementAt(i);
		    final Attribute att = dev_attr.get_attr_by_name(non_polled_name);

		    poll_period.add(att.get_polling_period());

		    if (att.get_polling_period() == 0) {
			Except.throw_exception("API_AttrNotPolled", "Attribute " + non_polled_name
				+ " not polled", "Device_2Impl.read_attributes");
		    } else {
			boolean found = false;
			final Vector napa = get_non_auto_polled_attr();

			for (j = 0; j < napa.size(); j++) {
			    final String napa_str = ((String) napa.elementAt(j)).toLowerCase();
			    if (napa_str.equals(non_polled_name.toLowerCase())) {
				found = true;
			    }
			}

			if (found) {
			    Except.throw_exception("API_AttrNotPolled", "Attribute "
				    + non_polled_name + " not polled",
				    "Device_2Impl.read_attributes");
			}
		    }
		}
		// Start polling
		final Util tg = Util.instance();
		final DServer adm_dev = tg.get_dserver_device();

		final DevVarLongStringArray send = new DevVarLongStringArray();
		send.lvalue = new int[1];
		send.svalue = new String[3];
		send.svalue[0] = device_name;
		send.svalue[1] = "attribute";

		for (i = 0; i < non_polled.size(); i++) {
		    send.lvalue[0] = (Integer) poll_period.elementAt(i);
		    send.svalue[2] = (String) non_polled.elementAt(i);

		    adm_dev.add_obj_polling(send, false);
		}
	    }

	    // Allocate memory for the AttributeValue structures
	    final int nb_attr = real_names.length;
	    back = new AttributeValue[nb_attr];

	    // For each attribute, check that some data are available in cache
	    // and that they
	    // are not too old
	    for (i = 0; i < nb_attr; i++) {
		PollObj polled_attr = null;
		for (j = 0; j < poll_list.size(); j++) {
		    final PollObj poll_obj = (PollObj) poll_list.elementAt(j);
		    if (poll_obj.get_type() == Tango_POLL_ATTR
			    && poll_obj.get_name().toLowerCase()
				    .equals(real_names[i].toLowerCase())) {
			polled_attr = poll_obj;
			break;
		    }
		}

		// Check that some data is available in cache
		if (polled_attr.is_ring_empty() == true) {
		    Except.throw_exception("API_NoDataYet",
			    "No data available in cache for attribute " + real_names[i],
			    "Device_2Impl.read_attributes");
		}

		// Check that data are still refreshed by the polling thread
		final long ctm = System.currentTimeMillis();
		int tv_sec = (int) (ctm / 1000);
		final int tv_usec = (int) (ctm - 1000 * tv_sec) * 1000;
		tv_sec = tv_sec - Tango_DELTA_T;

		final double last = polled_attr.get_last_insert_date();
		final double now_d = tv_sec + (double) tv_usec / 1000000;
		final double diff_d = now_d - last;
		if (diff_d > polled_attr.get_authorized_delta()) {
		    Except.throw_exception("API_NotUpdatedAnyMore", "Data in cache for attribute "
			    + real_names[i] + " not updated any more",
			    "Device_2Impl.read_attributes");
		}

		// Finally, after all these checks, get value and store it in
		// the
		// sequence sent back to user
		// In order to avoid unnecessary copy, don't use the assignement
		// operator of the
		// AttributeValue structure which copy each element and
		// therefore also copy
		// the Any object. The Any assignement operator is a deep copy!
		// Create a new sequence using the attribute buffer and insert
		// it into the
		// Any. The sequence inside the source Any has been created
		// using the attribute
		// data buffer.
		back[i] = polled_attr.get_last_attr_value();
	    }
	} catch (final DevFailed e) {
	    if (source == DevSource.CACHE) {
		throw e;
	    }
	    // if (att_in_fault == true) {
	    // throw e;
	    // }
	    polling_failed = true;
	}

	// If the source parameter is CACHE, returned data,
	// else call method reading attribute from device
	if (source == DevSource.CACHE_DEV && polling_failed == true) {
	    back = read_attributes(names);
	}
	return back;
    }
public AttributeValue [ ] read_attributes_2 ( final String [ ] names , final DevSource source ) throws DevFailed { Util . out4 . println ( "DeviceImpl.read_attributes_2 arrived src=" + source . value ( ) ) ; if ( source == DevSource . DEV ) { return read_attributes ( names ) ; } boolean polling_failed = false ; blackbox . insert_op ( Op_Read_Attr_2 ) ; AttributeValue [ ] back = null ; try { int i , j ; boolean all_attr = false ; final Vector poll_list = get_poll_obj_list ( ) ; final int nb_poll = poll_list . size ( ) ; final int nb_names = names . length ; String [ ] real_names = names ; if ( nb_names == 1 ) { final String att_name = names [ 0 ] ; if ( att_name . equals ( Tango_AllAttr ) ) { all_attr = true ; int nb_real = 0 ; for ( i = 0 ; i < nb_poll ; i ++ ) { final PollObj poll_obj = ( PollObj ) poll_list . elementAt ( i ) ; if ( poll_obj . get_type ( ) == Tango_POLL_ATTR ) { nb_real ++ ; } } real_names = new String [ nb_real ] ; for ( i = 0 , j = 0 ; i < nb_poll && j < nb_real ; i ++ ) { final PollObj poll_obj = ( PollObj ) poll_list . elementAt ( i ) ; if ( poll_obj . get_type ( ) == Tango_POLL_ATTR ) { real_names [ j ++ ] = poll_obj . get_name ( ) ; } } } } if ( all_attr == false ) { for ( i = 0 ; i < real_names . length ; i ++ ) { dev_attr . get_attr_ind_by_name ( real_names [ i ] ) ; } } final Vector non_polled = new Vector ( ) ; if ( all_attr == false ) { for ( i = 0 ; i < real_names . length ; i ++ ) { for ( j = 0 ; j < nb_poll ; j ++ ) { final PollObj poll_obj = ( PollObj ) poll_list . elementAt ( j ) ; if ( poll_obj . get_name ( ) . equals ( real_names [ i ] . toLowerCase ( ) ) ) { break ; } } if ( j == nb_poll ) { non_polled . add ( real_names [ i ] ) ; } } } final Vector poll_period = new Vector ( ) ; if ( non_polled . size ( ) != 0 ) { for ( i = 0 ; i < non_polled . size ( ) ; i ++ ) { final String non_polled_name = ( String ) non_polled . elementAt ( i ) ; final Attribute att = dev_attr . get_attr_by_name ( non_polled_name ) ; poll_period . add ( att . get_polling_period ( ) ) ; if ( att . get_polling_period ( ) == 0 ) { Except . throw_exception ( "API_AttrNotPolled" , "Attribute " + non_polled_name + " not polled" , "Device_2Impl.read_attributes" ) ; } else { boolean found = false ; final Vector napa = get_non_auto_polled_attr ( ) ; for ( j = 0 ; j < napa . size ( ) ; j ++ ) { final String napa_str = ( ( String ) napa . elementAt ( j ) ) . toLowerCase ( ) ; if ( napa_str . equals ( non_polled_name . toLowerCase ( ) ) ) { found = true ; } } if ( found ) { Except . throw_exception ( "API_AttrNotPolled" , "Attribute " + non_polled_name + " not polled" , "Device_2Impl.read_attributes" ) ; } } } final Util tg = Util . instance ( ) ; final DServer adm_dev = tg . get_dserver_device ( ) ; final DevVarLongStringArray send = new DevVarLongStringArray ( ) ; send . lvalue = new int [ 1 ] ; send . svalue = new String [ 3 ] ; send . svalue [ 0 ] = device_name ; send . svalue [ 1 ] = "attribute" ; for ( i = 0 ; i < non_polled . size ( ) ; i ++ ) { send . lvalue [ 0 ] = ( Integer ) poll_period . elementAt ( i ) ; send . svalue [ 2 ] = ( String ) non_polled . elementAt ( i ) ; adm_dev . add_obj_polling ( send , false ) ; } } final int nb_attr = real_names . length ; back = new AttributeValue [ nb_attr ] ; for ( i = 0 ; i < nb_attr ; i ++ ) { PollObj polled_attr = null ; for ( j = 0 ; j < poll_list . size ( ) ; j ++ ) { final PollObj poll_obj = ( PollObj ) poll_list . elementAt ( j ) ; if ( poll_obj . get_type ( ) == Tango_POLL_ATTR && poll_obj . get_name ( ) . toLowerCase ( ) . equals ( real_names [ i ] . toLowerCase ( ) ) ) { polled_attr = poll_obj ; break ; } } if ( polled_attr . is_ring_empty ( ) == true ) { Except . throw_exception ( "API_NoDataYet" , "No data available in cache for attribute " + real_names [ i ] , "Device_2Impl.read_attributes" ) ; } final long ctm = System . currentTimeMillis ( ) ; int tv_sec = ( int ) ( ctm / 1000 ) ; final int tv_usec = ( int ) ( ctm - 1000 * tv_sec ) * 1000 ; tv_sec = tv_sec - Tango_DELTA_T ; final double last = polled_attr . get_last_insert_date ( ) ; final double now_d = tv_sec + ( double ) tv_usec / 1000000 ; final double diff_d = now_d - last ; if ( diff_d > polled_attr . get_authorized_delta ( ) ) { Except . throw_exception ( "API_NotUpdatedAnyMore" , "Data in cache for attribute " + real_names [ i ] + " not updated any more" , "Device_2Impl.read_attributes" ) ; } back [ i ] = polled_attr . get_last_attr_value ( ) ; } } catch ( final DevFailed e ) { if ( source == DevSource . CACHE ) { throw e ; } polling_failed = true ; } if ( source == DevSource . CACHE_DEV && polling_failed == true ) { back = read_attributes ( names ) ; } return back ; }
=========================================================================