This commit is contained in:
maliakal_d 2020-06-29 17:40:41 +02:00
parent 902366fede
commit 0c045f0faa
11 changed files with 318 additions and 346 deletions

View File

@ -45,6 +45,7 @@ pthread_t pthread_virtual_tid;
int virtual_status = 0;
int virtual_stop = 0;
uint64_t virtual_pattern[MAX_PATTERN_LENGTH];
int64_t virtual_currentFrameNumber = 2;
#endif
// 1g readout
@ -2304,7 +2305,6 @@ void *start_timer(void *arg) {
}
// Send data
{
// loop over number of frames
for (int frameNr = 0; frameNr != numFrames; ++frameNr) {
@ -2329,11 +2329,10 @@ void *start_timer(void *arg) {
char packetData[packetSize];
memset(packetData, 0, packetSize);
// set header
sls_detector_header *header =
(sls_detector_header *)(packetData);
sls_detector_header *header = (sls_detector_header *)(packetData);
header->detType = (uint16_t)myDetectorType;
header->version = SLS_DETECTOR_HEADER_VERSION - 1;
header->frameNumber = frameNr;
header->frameNumber = virtual_currentFrameNumber;
header->packetNumber = i;
header->modId = 0;
header->row = detPos[X];
@ -2346,10 +2345,11 @@ void *start_timer(void *arg) {
sendUDPPacket(0, packetData, packetSize);
}
LOG(logINFO, ("Sent frame: %d\n", frameNr));
LOG(logINFO, ("Sent frame: %d [%lld]\n", frameNr,
(long long unsigned int)virtual_currentFrameNumber));
clock_gettime(CLOCK_REALTIME, &end);
int64_t timeNs = ((end.tv_sec - begin.tv_sec) * 1E9 +
(end.tv_nsec - begin.tv_nsec));
int64_t timeNs =
((end.tv_sec - begin.tv_sec) * 1E9 + (end.tv_nsec - begin.tv_nsec));
// sleep for (period - exptime)
if (frameNr < numFrames) { // if there is a next frame
@ -2357,7 +2357,7 @@ void *start_timer(void *arg) {
usleep((periodNs - timeNs) / 1000);
}
}
}
++virtual_currentFrameNumber;
}
closeUDPSocket(0);

View File

@ -40,6 +40,7 @@ sharedMem *thisMem;
pthread_t pthread_virtual_tid;
int virtual_status = 0;
int virtual_stop = 0;
int64_t virtual_currentFrameNumber = 2;
#endif
enum detectorSettings thisSettings = UNINITIALIZED;
@ -2321,8 +2322,6 @@ void *start_timer(void *arg) {
*((uint16_t *)(vetoData + i)) = i;
}
{
int frameHeaderNr = 0;
// loop over number of repeats
for (int repeatNr = 0; repeatNr != numRepeats; ++repeatNr) {
@ -2350,11 +2349,10 @@ void *start_timer(void *arg) {
char packetData[packetsize];
memset(packetData, 0, packetsize);
// set header
sls_detector_header *header =
(sls_detector_header *)(packetData);
sls_detector_header *header = (sls_detector_header *)(packetData);
header->detType = (uint16_t)myDetectorType;
header->version = SLS_DETECTOR_HEADER_VERSION - 1;
header->frameNumber = frameHeaderNr;
header->frameNumber = virtual_currentFrameNumber;
header->packetNumber = 0;
header->modId = 0;
header->row = detPos[X];
@ -2371,7 +2369,7 @@ void *start_timer(void *arg) {
if (vetoEnabled && numInterfaces == 2) {
// set header
veto_header *header = (veto_header *)(packetData2);
header->frameNumber = frameHeaderNr;
header->frameNumber = virtual_currentFrameNumber;
header->bunchId = 0;
// fill data
memcpy(packetData2 + sizeof(veto_header), vetoData,
@ -2379,11 +2377,10 @@ void *start_timer(void *arg) {
// send 1 packet = 1 frame
sendUDPPacket(1, packetData2, vetopacketsize);
}
++frameHeaderNr;
clock_gettime(CLOCK_REALTIME, &end);
LOG(logINFO,
("Sent frame: %d (bursts: %d)\n", frameNr, repeatNr));
("Sent frame: %d (bursts: %d) [%lld]\n", frameNr, repeatNr,
(long long unsigned int)virtual_currentFrameNumber));
clock_gettime(CLOCK_REALTIME, &end);
int64_t timeNs = ((end.tv_sec - begin.tv_sec) * 1E9 +
(end.tv_nsec - begin.tv_nsec));
@ -2393,6 +2390,7 @@ void *start_timer(void *arg) {
usleep((periodNs - timeNs) / 1000);
}
}
++virtual_currentFrameNumber;
}
clock_gettime(CLOCK_REALTIME, &rend);
int64_t timeNs = ((rend.tv_sec - rbegin.tv_sec) * 1E9 +
@ -2405,7 +2403,6 @@ void *start_timer(void *arg) {
}
}
}
}
closeUDPSocket(0);
if (vetoEnabled && numInterfaces == 2) {

View File

@ -38,6 +38,7 @@ pthread_t pthread_virtual_tid;
int virtual_status = 0;
int virtual_stop = 0;
int highvoltage = 0;
int64_t virtual_currentFrameNumber = 2;
#endif
int detPos[2] = {};
@ -1587,8 +1588,6 @@ void *start_timer(void *arg) {
}
// Send data
{
uint16_t frameHeaderNr = 2;
// loop over number of frames
for (int frameNr = 0; frameNr != numFrames; ++frameNr) {
@ -1613,8 +1612,8 @@ void *start_timer(void *arg) {
char packetData[packetSize];
memset(packetData, 0, packetSize);
// set header
*((uint16_t *)(packetData)) = frameHeaderNr;
++frameHeaderNr;
*((uint16_t *)(packetData)) = virtual_currentFrameNumber;
++virtual_currentFrameNumber;
// fill data
memcpy(packetData + 4, imageData + srcOffset, dataSize);
@ -1622,10 +1621,11 @@ void *start_timer(void *arg) {
sendUDPPacket(0, packetData, packetSize);
}
LOG(logINFO, ("Sent frame: %d\n", frameNr));
LOG(logINFO,
("Sent frame: %d [%d]\n", frameNr, virtual_currentFrameNumber));
clock_gettime(CLOCK_REALTIME, &end);
int64_t timeNs = ((end.tv_sec - begin.tv_sec) * 1E9 +
(end.tv_nsec - begin.tv_nsec));
int64_t timeNs =
((end.tv_sec - begin.tv_sec) * 1E9 + (end.tv_nsec - begin.tv_nsec));
// sleep for (period - exptime)
if (frameNr < numFrames) { // if there is a next frame
@ -1634,7 +1634,6 @@ void *start_timer(void *arg) {
}
}
}
}
closeUDPSocket(0);

View File

@ -43,6 +43,7 @@ pthread_t pthread_virtual_tid;
int virtual_status = 0;
int virtual_stop = 0;
uint64_t virtual_pattern[MAX_PATTERN_LENGTH];
int64_t virtual_currentFrameNumber = 2;
#endif
// 1g readout
@ -1963,7 +1964,7 @@ void *start_timer(void *arg) {
sls_detector_header *header = (sls_detector_header *)(packetData);
header->detType = (uint16_t)myDetectorType;
header->version = SLS_DETECTOR_HEADER_VERSION - 1;
header->frameNumber = frameNr;
header->frameNumber = virtual_currentFrameNumber;
header->packetNumber = i;
header->modId = 0;
header->row = detPos[X];
@ -1976,7 +1977,8 @@ void *start_timer(void *arg) {
sendUDPPacket(0, packetData, packetSize);
}
LOG(logINFO, ("Sent frame: %d\n", frameNr));
LOG(logINFO, ("Sent frame: %d [%lld]\n", frameNr,
(long long unsigned int)virtual_currentFrameNumber));
clock_gettime(CLOCK_REALTIME, &end);
int64_t timeNs =
((end.tv_sec - begin.tv_sec) * 1E9 + (end.tv_nsec - begin.tv_nsec));
@ -1987,6 +1989,7 @@ void *start_timer(void *arg) {
usleep((periodNs - timeNs) / 1000);
}
}
++virtual_currentFrameNumber;
}
closeUDPSocket(0);

View File

@ -38,6 +38,7 @@ sharedMem *thisMem;
pthread_t pthread_virtual_tid;
int virtual_status = 0;
int virtual_stop = 0;
int64_t virtual_currentFrameNumber = 2;
#endif
sls_detector_module *detectorModules = NULL;
@ -2073,7 +2074,7 @@ void *start_timer(void *arg) {
sls_detector_header *header = (sls_detector_header *)(packetData);
header->detType = (uint16_t)myDetectorType;
header->version = SLS_DETECTOR_HEADER_VERSION - 1;
header->frameNumber = frameNr + 1;
header->frameNumber = virtual_currentFrameNumber;
header->packetNumber = i;
header->modId = 0;
header->row = detPos[X];
@ -2086,7 +2087,8 @@ void *start_timer(void *arg) {
sendUDPPacket(0, packetData, packetSize);
}
LOG(logINFO, ("Sent frame: %d\n", frameNr));
LOG(logINFO, ("Sent frame: %d [%lld]\n", frameNr,
(long long unsigned int)virtual_currentFrameNumber));
clock_gettime(CLOCK_REALTIME, &end);
int64_t timeNs =
((end.tv_sec - begin.tv_sec) * 1E9 + (end.tv_nsec - begin.tv_nsec));
@ -2097,6 +2099,7 @@ void *start_timer(void *arg) {
usleep((periodNs - timeNs) / 1000);
}
}
++virtual_currentFrameNumber;
}
closeUDPSocket(0);

View File

@ -36,6 +36,7 @@ int set_firmware_test(int);
int set_bus_test(int);
int set_image_test_mode(int);
int get_image_test_mode(int);
enum DACINDEX getDACIndex(enum dacIndex ind);
int set_dac(int);
int get_adc(int);
int write_register(int);
@ -43,6 +44,7 @@ int read_register(int);
int set_module(int);
int set_settings(int);
int get_threshold_energy(int);
int start_state_machine(int blocking, int file_des);
int start_acquisition(int);
int stop_acquisition(int);
int get_run_status(int);

View File

@ -710,20 +710,8 @@ int get_image_test_mode(int file_des) {
return Server_SendResult(file_des, INT32, &retval, sizeof(retval));
}
int set_dac(int file_des) {
ret = OK;
memset(mess, 0, sizeof(mess));
int args[3] = {-1, -1, -1};
int retval = -1;
if (receiveData(file_des, args, sizeof(args), INT32) < 0)
return printSocketReadError();
enum dacIndex ind = args[0];
int mV = args[1];
int val = args[2];
enum DACINDEX getDACIndex(enum dacIndex ind) {
enum DACINDEX serverDacIndex = 0;
// check if dac exists for this detector
switch (ind) {
#ifdef GOTTHARDD
@ -1000,6 +988,22 @@ int set_dac(int file_des) {
modeNotImplemented("Dac Index", (int)ind);
break;
}
return serverDacIndex;
}
int set_dac(int file_des) {
ret = OK;
memset(mess, 0, sizeof(mess));
int args[3] = {-1, -1, -1};
int retval = -1;
if (receiveData(file_des, args, sizeof(args), INT32) < 0)
return printSocketReadError();
enum dacIndex ind = args[0];
int mV = args[1];
int val = args[2];
enum DACINDEX serverDacIndex = getDACIndex(ind);
// index exists
if (ret == OK) {
@ -1647,11 +1651,14 @@ int get_threshold_energy(int file_des) {
return Server_SendResult(file_des, INT32, &retval, sizeof(retval));
}
int start_acquisition(int file_des) {
int start_state_machine(int blocking, int file_des) {
ret = OK;
memset(mess, 0, sizeof(mess));
LOG(logDEBUG1, ("Starting Acquisition\n"));
if (blocking) {
LOG(logINFOBLUE, ("Blocking Acquisition\n"));
} else {
LOG(logINFOBLUE, ("Unblocking Acquisition\n"));
}
// only set
if (Server_VerifyLock() == OK) {
#if defined(MOENCHD)
@ -1723,21 +1730,27 @@ int start_acquisition(int file_des) {
}
for (int i = 0; i != times; ++i) {
if (scanTrimbits) {
LOG(logINFOBLUE, ("Trimbits scan %d/%d: [%d]\n", i, times,
scanSteps[i]));
#ifdef EIGERD
setAllTrimbits(scanSteps[i]);
#else
LOG(logERROR, ("trimbit scan not implemented!\n"));
#endif
} else {
setDac(scanDac, scanSteps[i], 0);
} else if (numScanSteps > 0) {
LOG(logINFOBLUE, ("Dac [%d] scan %d/%d: [%d]\n", scanDac, i,
times, scanSteps[i]));
setDAC(scanDac, scanSteps[i], 0);
int retval = getDAC(scanDac, 0);
if (abs(retval - val) > 5) {
if (abs(retval - scanSteps[i]) > 5) {
ret = FAIL;
sprintf(mess, "Setting dac %d : wrote %d but read %d\n",
dacIndex, scanSteps[i], retval);
scanDac, scanSteps[i], scanSteps[i]);
LOG(logERROR, (mess));
break;
}
} else {
LOG(logINFOBLUE, ("Normal Acquisition (not scan)\n"));
}
ret = startStateMachine();
if (ret == FAIL) {
@ -1752,6 +1765,10 @@ int start_acquisition(int file_des) {
LOG(logERROR, (mess));
break;
}
// blocking or scan
if (blocking || times > 1) {
readFrame(&ret, mess);
}
}
}
LOG(logDEBUG2, ("Starting Acquisition ret: %d\n", ret));
@ -1759,6 +1776,8 @@ int start_acquisition(int file_des) {
return Server_SendResult(file_des, INT32, NULL, 0);
}
int start_acquisition(int file_des) { return start_state_machine(0, file_des); }
int stop_acquisition(int file_des) {
ret = OK;
memset(mess, 0, sizeof(mess));
@ -1789,98 +1808,7 @@ int get_run_status(int file_des) {
}
int start_and_read_all(int file_des) {
ret = OK;
memset(mess, 0, sizeof(mess));
LOG(logDEBUG1, ("Starting Acquisition and read all frames\n"));
// start state machine
LOG(logDEBUG1, ("Starting Acquisition\n"));
// only set
if (Server_VerifyLock() == OK) {
#if defined(MOENCHD)
if (getNumAnalogSamples() <= 0) {
ret = FAIL;
sprintf(mess,
"Could not start acquisition. Invalid number of analog "
"samples: %d.\n",
getNumAnalogSamples());
LOG(logERROR, (mess));
} else
#endif
#if defined(CHIPTESTBOARDD)
if ((getReadoutMode() == ANALOG_AND_DIGITAL ||
getReadoutMode() == ANALOG_ONLY) &&
(getNumAnalogSamples() <= 0)) {
ret = FAIL;
sprintf(mess,
"Could not start acquisition. Invalid number of analog "
"samples: %d.\n",
getNumAnalogSamples());
LOG(logERROR, (mess));
} else if ((getReadoutMode() == ANALOG_AND_DIGITAL ||
getReadoutMode() == DIGITAL_ONLY) &&
(getNumDigitalSamples() <= 0)) {
ret = FAIL;
sprintf(mess,
"Could not start acquisition. Invalid number of digital "
"samples: %d.\n",
getNumDigitalSamples());
LOG(logERROR, (mess));
} else
#endif
#ifdef EIGERD
// check for hardware mac and hardware ip
if (udpDetails.srcmac != getDetectorMAC()) {
ret = FAIL;
uint64_t sourcemac = getDetectorMAC();
char src_mac[50];
getMacAddressinString(src_mac, 50, sourcemac);
sprintf(mess,
"Invalid udp source mac address for this detector. Must be "
"same as hardware detector mac address %s\n",
src_mac);
LOG(logERROR, (mess));
} else if (!enableTenGigabitEthernet(GET_FLAG) &&
(udpDetails.srcip != getDetectorIP())) {
ret = FAIL;
uint32_t sourceip = getDetectorIP();
char src_ip[INET_ADDRSTRLEN];
getIpAddressinString(src_ip, sourceip);
sprintf(
mess,
"Invalid udp source ip address for this detector. Must be same "
"as hardware detector ip address %s in 1G readout mode \n",
src_ip);
LOG(logERROR, (mess));
} else
#endif
if (configured == FAIL) {
ret = FAIL;
strcpy(mess, "Could not start acquisition because ");
strcat(mess, configureMessage);
LOG(logERROR, (mess));
} else {
ret = startStateMachine();
if (ret == FAIL) {
#if defined(VIRTUAL) || defined(CHIPTESTBOARDD) || defined(MOENCHD)
sprintf(mess,
"Could not start acquisition. Could not create udp "
"socket in server. Check udp_dstip & udp_dstport.\n");
#else
sprintf(mess, "Could not start acquisition\n");
#endif
LOG(logERROR, (mess));
}
}
LOG(logDEBUG2, ("Starting Acquisition ret: %d\n", ret));
}
// lock or acquisition start error
if (ret == FAIL)
return Server_SendResult(file_des, INT32, NULL, 0);
// read all (again validate lock, but should pass and not fail)
return read_all(file_des);
return start_state_machine(1, file_des);
}
int read_all(int file_des) {
@ -7542,7 +7470,8 @@ int disable_scan(int file_des) {
free(scanSteps);
scanSteps = NULL;
}
setNumFrames(1);
int64_t arg = 1;
setNumFrames(arg);
int64_t retval = getNumFrames();
LOG(logDEBUG1, ("retval num frames %lld\n", (long long int)retval));
validate64(arg, retval, "set number of frames", DEC);
@ -7564,6 +7493,13 @@ int enable_scan(int file_des) {
int endOffset = args[2];
int stepSize = args[3];
scanTrimbits = 0;
if ((startOffset < endOffset && stepSize <= 0) ||
(endOffset < startOffset && stepSize >= 0)) {
ret = FAIL;
sprintf(mess, "Invalid scan parameters\n");
LOG(logERROR, (mess));
} else {
// trimbit scan
if (args[0] == TRIMBIT_SCAN) {
#ifdef EIGERD
@ -7574,6 +7510,7 @@ int enable_scan(int file_des) {
LOG(logERROR, (mess));
} else {
scanTrimbits = 1;
LOG(logINFOBLUE, ("Trimbit scan enabled\n"));
// changes settings to undefined
setSettings(UNDEFINED);
LOG(logERROR,
@ -7587,11 +7524,34 @@ int enable_scan(int file_des) {
LOG(logERROR, (mess));
#endif
} else {
ret = converttodac(args[0], &scanDac);
switch ((enum dacIndex)args[0]) {
case HIGH_VOLTAGE:
#ifdef EIGERD
case IO_DELAY:
#elif CHIPTESTBOARDD
case ADC_VPP:
case V_POWER_A:
case V_POWER_B:
case V_POWER_C:
case V_POWER_D:
case V_POWER_IO:
case V_POWER_CHIP:
case V_LIMIT:
#elif MOENCHD
case ADC_VPP:
case V_LIMIT:
#endif
modeNotImplemented("Scan Dac Index", args[0]);
break;
default:
break;
}
scanDac = getDACIndex(args[0]);
if (ret == FAIL) {
sprintf(mess,
sprintf(
mess,
"Cannot enable scan. Dac index %d not implemented for "
"this detector\n",
"this detector for scanning\n",
args[0]);
LOG(logERROR, (mess));
} else if (startOffset < 0 || startOffset > getMaxDacSteps() ||
@ -7611,8 +7571,8 @@ int enable_scan(int file_des) {
LOG(logERROR, (mess));
}
#endif
#ifdef EIGERD
if (ret == OK) {
#ifdef EIGERD
// changing dac changes settings to undefined
switch (scanDac) {
case E_VCMP_LL:
@ -7622,31 +7582,36 @@ int enable_scan(int file_des) {
case E_VRPREAMP:
case E_VCP:
setSettings(UNDEFINED);
LOG(logERROR, ("Settings has been changed "
LOG(logERROR,
("Settings has been changed "
"to undefined (changed specific dacs)\n"));
break;
default:
break;
}
}
#endif
LOG(logINFOBLUE, ("Dac [%d] scan enabled\n", scanDac));
}
}
}
if (ret == OK) {
scan = 1;
numScanSteps = ((startOffset - endOffset) / stepSize) + 1;
numScanSteps = (abs(endOffset - startOffset) / abs(stepSize)) + 1;
if (scanSteps != NULL) {
free(scanSteps);
}
scanSteps = malloc(numScanSteps * sizeof(int));
for (int i = 0; i != numScanSteps; ++i) {
scanSteps[i] = startOffset + i * stepSize;
LOG(logDEBUG1, ("scansteps[%d]:%d\n", i, scanSteps[i]));
}
LOG(logINFOBLUE,
("Enabling scan for dac[%d], start[%d], end[%d], "
"stepsize[%d], nsteps[%d]\n",
ind, startOffset, endOffset, stepSize, numScanSteps));
setNumFrames(1);
scanDac, startOffset, endOffset, stepSize, numScanSteps));
int64_t arg = 1;
setNumFrames(arg);
int64_t retval = getNumFrames();
LOG(logDEBUG1, ("retval num frames %lld\n", (long long int)retval));
validate64(arg, retval, "set number of frames", DEC);

View File

@ -997,8 +997,10 @@ std::string CmdProxy::Scan(int action) {
if (action == defs::HELP_ACTION) {
os << "[dac_name|0|trimbit_scan] [start_val] [stop_val] "
"[step_size]\n\tConfigures to scan "
"dac. Must acquire after this. To cancel the scan configuration "
"set dac to '0' without further arguments."
"dac and sets number of frames to number of steps. Must acquire "
"after this. To cancel the scan configuration "
"set dac to '0' without further arguments. This also sets number "
"of frames back to 1."
"\n\t[Eiger]Use trimbit_scan as dac name for a trimbit scan."
<< '\n';
} else if (action == defs::GET_ACTION) {
@ -1014,10 +1016,10 @@ std::string CmdProxy::Scan(int action) {
} else if (args.size() != 4) {
WrongNumberOfParameters(4);
} else {
auto t = det->enableScan(
StringTo<defs::dacIndex>(args[0]), StringTo<int>(args[1]),
StringTo<int>(args[2]), StringTo<int>(args[3]));
auto nsteps = det->getNumScanSteps().tsquash(
det->enableScan(StringTo<defs::dacIndex>(args[0]),
StringTo<int>(args[1]), StringTo<int>(args[2]),
StringTo<int>(args[3]));
auto nsteps = det->getNumberOfScanSteps().tsquash(
"inconsistent number of scan steps");
os << "scan enabled for " << nsteps << " steps" << '\n';
}

View File

@ -562,25 +562,26 @@ void Detector::sendSoftwareTrigger(Positions pos) {
pimpl->Parallel(&Module::sendSoftwareTrigger, pos);
}
Result<bool> getScan(Positions pos = {}) const {
Result<bool> Detector::getScan(Positions pos) const {
return pimpl->Parallel(&Module::getScan, pos);
}
Result<int> getNumberOfScanSteps(Positions pos = {}) const {
Result<int> Detector::getNumberOfScanSteps(Positions pos) const {
return pimpl->Parallel(&Module::getNumberOfScanSteps, pos);
}
void disableScan() {
pimpl->Parallel(&Module::disableScan);
void Detector::disableScan() {
pimpl->Parallel(&Module::disableScan, {});
setNumberOfFrames(1);
}
void Detector::enableScan(const defs::dacIndex dac, const int start_offset,
const int end_offset, const int step_size) {
pimpl->Parallel(&Module::scan, start_offset, end_offset, step_size, {-1});
pimpl->Parallel(&Module::enableScan, {}, dac, start_offset, end_offset,
step_size);
auto t =
getNumberOfScanSteps().tsquash("inconsistent number of scan steps");
setNumberOfFrames(nsteps);
setNumberOfFrames(t);
}
// Network Configuration (Detector<->Receiver)

View File

@ -451,11 +451,11 @@ void Module::setStartingFrameNumber(uint64_t value) {
void Module::sendSoftwareTrigger() { sendToDetectorStop(F_SOFTWARE_TRIGGER); }
bool Module::getScan() const {
bool Module::getScan() {
return static_cast<bool>(sendToDetector<int>(F_GET_SCAN));
}
int Module::getNumberOfScanSteps() const {
int Module::getNumberOfScanSteps() {
return sendToDetector<int>(F_GET_NUM_SCAN_STEPS);
}

View File

@ -167,8 +167,8 @@ class Module : public virtual slsDetectorDefs {
uint64_t getStartingFrameNumber();
void setStartingFrameNumber(uint64_t value);
void sendSoftwareTrigger();
bool getScan() const;
int getNumberOfScanSteps() const;
bool getScan();
int getNumberOfScanSteps();
void disableScan();
void enableScan(const defs::dacIndex dac, const int start_offset,
const int end_offset, const int step_size);