Commit 944d5e56 by Tomasz Ciesielczyk

project usage and dependency update

parent b90f8673
......@@ -10,7 +10,6 @@ import psnc.m2dc.rtm.pcm.PCMApi
import psnc.m2dc.rtm.properties.keys.Keys
import psnc.m2dc.rtm.rest.Handlers
import psnc.m2dc.rtm.rest.auth.RESTAuth
import psnc.m2dc.rtm.rpm.RPMApiImpl
import psnc.m2dc.rtm.utils.Timer
import psnc.m2dc.rtm.utils.logError
import psnc.m2dc.rtm.utils.logInfo
......@@ -31,7 +30,7 @@ object ServerInitializer {
ESMApi.init()
setDefaultPriorities()
save()
LightStorage.saveStorage()
// StorageKeys.POWER_LIMIT = Values.powerLimit(440.0)
// val a =PCMApi.instance().predictPCMActions()
// a.generateScripts().toJson(true)
......@@ -51,21 +50,24 @@ object ServerInitializer {
}
}
/**
* set scan thread
*/
private fun setScanner() {
// printConsole("scanner status: ${Keys.RTM.scan_thread.getBoolean()}")
val isRunning = RTMScannerWorker.isRunning
// zdebugowac
if (Keys.RTM.scan_thread.getBoolean() && !isRunning)
logError("RTM scanner is not working, however it should")
else if(!Keys.RTM.scan_thread.getBoolean() ){
else if (!Keys.RTM.scan_thread.getBoolean()) {
logInfo("RTM scanner is off")
}
// printConsole("scanner status2: $isRunning")
}
private fun save() {
RPMApiImpl.instance().storage.save()
}
// private fun save() {
// RPMApiImpl.instance().storage.save()
// }
private fun loadConfig() {
Timer.start()
......
package psnc.m2dc.rtm.commands.java
val APP_VERSION = "1.0.425_63508"
\ No newline at end of file
val APP_VERSION = "1.0.426_28177"
\ No newline at end of file
package psnc.m2dc.rtm.client
const val APP_VERSION = "1.1.425_63509"
\ No newline at end of file
const val APP_VERSION = "1.1.426_28178"
\ No newline at end of file
......@@ -15,7 +15,7 @@ static def getDate() {
return (diff_days/day).toInteger()+"_"+(diff_seconds/1000).toInteger()
}
version '1.2.' + getDate()
version '1.3.' + getDate()
buildscript {
ext.kotlin_version = '1.2.0'
......@@ -45,7 +45,6 @@ dependencies {
compile "org.slf4j:slf4j-log4j12:1.7.25"
compile "org.slf4j:slf4j-api:1.7.25"
compile fileTree(dir: '../lib', include: '*.jar')
// compile files('"$rootProject.projectDir\\lib\\AppData-0.5.4.jar')
compile "com.thoughtworks.xstream:xstream:1.4.10"
compile "org.jsoup:jsoup:1.10.3"
compile "org.apache.directory.studio:org.apache.commons.codec:1.8"
......
......@@ -12,7 +12,6 @@ import java.util.*
object ActionCache {
//#region properties
private val lock = Any()
/**
* failed api requests cache
* key - api_resource_id
......
......@@ -81,7 +81,6 @@ class ChassisDAO(val storage: TreeStorage) {
fun cleanNodeUtil() {
critical {
val util = getRCUUtil()
val interval = TimeInterval.DEFAULT()
util.nodeUtilization.removeIf { !it.timeInterval.isExpired(interval) }
util.save("RCUUtil")
......
package psnc.m2dc.rtm.dao
import psnc.m2dc.rtm.dao.filestorage.ResourceManagerImpl
object DAO {
/**
......
......@@ -29,19 +29,90 @@ abstract class ResourceManager : DataDAO() {
}
}
// abstract fun getResources(): HashMap<String, Resource>?
// abstract fun save(resources: HashMap<String, Resource>)
abstract fun saveOrUpdate(resources: HashMap<String, Resource>)
abstract fun getRecsHosts(): List<String>?
abstract fun saveRecsHosts(list: List<String>)
abstract fun getResourceType(r: Resource): ResourceType
abstract fun getResourceType(typeId: String): ResourceType?
abstract fun addResourceType(type: ResourceType)
// fun throwResourceTypeNotFound(typeId: String) {
// throw java.lang.IllegalArgumentException("Type not found:$typeId")
// }
fun getRecsHosts(): List<String>? {
val key = getKey(RPMApi.RECS_HOSTS)
return LightStorage.getObject<List<String>>(key)
// if (!this.storage.notNull(key)) {
// return null
// }
// return this.storage.get<List<String>>(key)
}
fun saveRecsHosts(list: List<String>) {
synchronized(this) {
val key = getKey(RPMApi.RECS_HOSTS)
list.save(key)
// val current = this.getRecsHosts() ?: List<String>()
// resources.forEach { id, resource ->
// current[id] = resource
// }
// storage.put(key, list)
}
}
fun insertResource(resource: Resource) {
resource.toJson()
}
fun saveOrUpdate(resources: HashMap<String, Resource>) {
synchronized(this) {
val current = /*this.getResources() ?:*/ HashMap<String, Resource>()
resources.forEach { id, resource ->
if (current.containsKey(id)) {
val updatedResource = update(resource, current[id]!!)
current[id] = updatedResource
} else {
current[id] = resource
}
}
}
}
private fun update(resource: Resource, old: Resource): Resource {
// resourceMap: HashMap<String, Resource>, overwrite: Boolean = true
var r = resource
// r = Resource(r.id, r.typeId, r.parentResource ?: old.parentResource,
// r.childResources ?: old.childResources, r.properties ?: old.properties ?: HashMap(),
// r.resourceType ?: old.resourceType )
r = Resource(r.id, r.typeId, r.parentResource ?: old.parentResource,
r.childResources ?: old.childResources, r.properties,
r.resourceType ?: old.resourceType)
// else {
// r = Resource(temp.id, temp.typeId, temp.parentResource ?: r.parentResource,
// temp.childResources ?: r.childResources, temp.properties ?: r.properties ?: HashMap(),
// temp.resourceType ?: r.resourceType ?: null)
// }
// if (old.properties != null) {
old.properties.entries.forEach({
// if (overwrite) {
// r.properties!!.put(it.key, it.value)
// } else {
r.properties.putIfAbsent(it.key, it.value)
// }
})
// }
return r
}
fun getResourceType(r: Resource): ResourceType {
return Keys.RTM.resource_type_map.getNullable(r.typeId) ?: throw NullPointerException(
"Cannot find resource type for resource: ${r.id}:${r.typeId}")
}
fun getResourceType(typeId: String): ResourceType? {
return Keys.RTM.resource_type_map.getNullable(typeId)
}
fun addResourceType(type: ResourceType) {
Keys.RTM.resource_type_map.put(type.id, type)
}
//#region read
......@@ -394,7 +465,7 @@ abstract class ResourceManager : DataDAO() {
}
} catch (e: TaskExecutor.DuplicateExecutionException) {
logWarn(e, "duplicate task for $id")
} catch (e: Exception) {
} catch (e: Exception) {
logError(e, "Cannot get result for $id")
}
}
......
......@@ -30,8 +30,6 @@ object SettingsDAO : DataDAO() {
// sensorNameList.forEach { sensorName ->
// sensorMap.add(sensorName, typeName, method)
// }
}
......@@ -73,6 +71,9 @@ object SettingsDAO : DataDAO() {
}
}
/**
* load power model model in pmx format
*/
private fun loadXModel(file: File): ComponentPowerModel? {
try {
// nie wczytuje modeli poprawnie
......@@ -125,13 +126,9 @@ object SettingsDAO : DataDAO() {
}
// fun addModel(name: String, model: ComponentPowerModel) {
// synchronized(this) {
// Keys.PCM.model_map.set(name, model)
// save()
// }
// }
/**
* read power model basic power details
*/
private fun loadPowerModelDetails(f: File): PowerModelDetails {
val set = HashSet<Double>()
var first = true
......@@ -203,19 +200,6 @@ object SettingsDAO : DataDAO() {
return cm
}
/* fun loadSensorMap() {
val sensorMap = this.getSensorMap()!!
RTMProperties.getJson<SensorMap>(RTMProperties.parsePath(Keys.Default.sensor_map_file.get()))?.let { newMap ->
newMap.typeMap.forEach { typeName, sensorNameList ->
val method = newMap.typeMethodMap[typeName]
sensorNameList.forEach { sensorName ->
sensorMap.add(sensorName, typeName, method)
}
}
}
}
*/
}
\ No newline at end of file
package psnc.m2dc.rtm.dao.filestorage
import psnc.m2dc.rtm.dao.LightStorage
import psnc.m2dc.rtm.dao.ResourceManager
import psnc.m2dc.rtm.dao.save
import psnc.m2dc.rtm.model.rpm.Resource
import psnc.m2dc.rtm.model.rpm.ResourceType
import psnc.m2dc.rtm.properties.keys.Keys
import psnc.m2dc.rtm.rpm.RPMApi
import psnc.m2dc.rtm.utils.toJson
/**
*
* Created by Tomek on 2018-05-10.
*/
class ResourceManagerImpl() : ResourceManager() {
override fun getRecsHosts(): List<String>? {
val key = getKey(RPMApi.RECS_HOSTS)
return LightStorage.getObject<List<String>>(key)
// if (!this.storage.notNull(key)) {
// return null
// }
// return this.storage.get<List<String>>(key)
}
override fun saveRecsHosts(list: List<String>) {
synchronized(this) {
val key = getKey(RPMApi.RECS_HOSTS)
list.save(key)
// val current = this.getRecsHosts() ?: List<String>()
// resources.forEach { id, resource ->
// current[id] = resource
// }
// storage.put(key, list)
}
}
// private fun loadRecsHostDetails(): List<String> {
//
// val key = this.getKey(RPMApi.RECS_HOSTS).toString() + ""
// // p rintln("key: " + key.toString())
// if (!this.storage.notNull(key)) {
// storage.put(key, RECSApi.Instance.loadRECSHosts(), RTMProperties.INFINITY_DATA_TIMEOUT)
// }
// return this.storage.get<List<String>>(key)
// }
// override fun save(resources: HashMap<String, Resource>) {
// synchronized(this) {
// // logDebug("test")
// val current = /* this.getResources() ?:*/ HashMap<String, Resource>()
// // logDebug("test2")
// resources.forEach { id, resource ->
// // logDebug("save resource: $id")
// current[id] = resource
// }
// val key = getKey(RPMApi.RESOURCES_DATA)
//
// storage.put(key, current, ResourceMapWrapperInstance)
// }
// }
fun insertResource(resource: Resource) {
resource.toJson()
}
override fun saveOrUpdate(resources: HashMap<String, Resource>) {
synchronized(this) {
val current = /*this.getResources() ?:*/ HashMap<String, Resource>()
resources.forEach { id, resource ->
if (current.containsKey(id)) {
val updatedResource = update(resource, current[id]!!)
current[id] = updatedResource
} else {
current[id] = resource
}
}
}
}
// override fun getResources(): HashMap<String, Resource>? {
//
// val key = getKey(RPMApi.RESOURCES_DATA)
// if (!this.storage.notNull(key)) {
// return null
// }
// return this.storage.get<HashMap<String, Resource>>(key)
// }
private fun update(resource: Resource, old: Resource): Resource {
// resourceMap: HashMap<String, Resource>, overwrite: Boolean = true
var r = resource
// r = Resource(r.id, r.typeId, r.parentResource ?: old.parentResource,
// r.childResources ?: old.childResources, r.properties ?: old.properties ?: HashMap(),
// r.resourceType ?: old.resourceType )
r = Resource(r.id, r.typeId, r.parentResource ?: old.parentResource,
r.childResources ?: old.childResources, r.properties,
r.resourceType ?: old.resourceType)
// else {
// r = Resource(temp.id, temp.typeId, temp.parentResource ?: r.parentResource,
// temp.childResources ?: r.childResources, temp.properties ?: r.properties ?: HashMap(),
// temp.resourceType ?: r.resourceType ?: null)
// }
// if (old.properties != null) {
old.properties.entries.forEach({
// if (overwrite) {
// r.properties!!.put(it.key, it.value)
// } else {
r.properties.putIfAbsent(it.key, it.value)
// }
})
// }
return r
}
override fun getResourceType(r: Resource): ResourceType {
return Keys.RTM.resource_type_map.getNullable(r.typeId) ?: throw NullPointerException(
"Cannot find resource type for resource: ${r.id}:${r.typeId}")
}
override fun getResourceType(typeId: String): ResourceType? {
return Keys.RTM.resource_type_map.getNullable(typeId)
}
override fun addResourceType(type: ResourceType) {
Keys.RTM.resource_type_map.put(type.id, type)
}
// this.storage.get<T>(key,default)
}
\ No newline at end of file
package psnc.m2dc.rtm.properties
import com.casstomdev.appdata.ObjectTypeWrapper
import com.casstomdev.appdata.ObjectWrapper
import com.casstomdev.appdata.ObjectWrapperSerializer
import com.google.gson.JsonDeserializationContext
import com.google.gson.JsonElement
import com.google.gson.JsonSerializationContext
import psnc.m2dc.rtm.utils.ComponentPowerModelMapWrapper
import psnc.m2dc.rtm.utils.NodePriorityMapWrapper
import psnc.m2dc.rtm.utils.ResourceMapWrapper
import java.lang.reflect.Type
/**
*
* Created by Tomek on 2017-12-28.
*/
class CustomObjectSerializer : ObjectWrapperSerializer() {
companion object {
val types = HashMap<String, Type>()
init {
setType(NodePriorityMapWrapper())
setType(ResourceMapWrapper())
setType(ComponentPowerModelMapWrapper())
}
fun setType(wrapper: com.casstomdev.appdata.ObjectTypeWrapper) {
types[wrapper::class.java.name] = wrapper.type
}
}
override fun serialize(wrapper: ObjectWrapper<Any?>, type: Type,
jsonSerializationContext: JsonSerializationContext): JsonElement {
return jsonSerializationContext.serialize(wrapper, type)
}
override fun deserialize(jsonElement: JsonElement, type: Type,
jsonDeserializationContext: JsonDeserializationContext): ObjectWrapper<Any?>? {
try {
val jsonObj = jsonElement.getAsJsonObject()
val typeStr = jsonObj.get("type").getAsString()
val objectType = Class.forName(typeStr)
val obj: Any?
// if (typeStr.toLowerCase().contains("resourcemapwrapper")) {
// println("fdsaf")
//package psnc.m2dc.rtm.properties
//
//import com.casstomdev.appdata.ObjectTypeWrapper
//import com.casstomdev.appdata.ObjectWrapper
//import com.casstomdev.appdata.ObjectWrapperSerializer
//import com.google.gson.JsonDeserializationContext
//import com.google.gson.JsonElement
//import com.google.gson.JsonSerializationContext
//import psnc.m2dc.rtm.utils.ComponentPowerModelMapWrapper
//import psnc.m2dc.rtm.utils.NodePriorityMapWrapper
//import psnc.m2dc.rtm.utils.ResourceMapWrapper
//import java.lang.reflect.Type
//
//
///**
// *
// * Created by Tomek on 2017-12-28.
// */
//class CustomObjectSerializer : ObjectWrapperSerializer() {
// companion object {
// val types = HashMap<String, Type>()
//
// init {
// setType(NodePriorityMapWrapper())
// setType(ResourceMapWrapper())
// setType(ComponentPowerModelMapWrapper())
// }
//
// fun setType(wrapper: com.casstomdev.appdata.ObjectTypeWrapper) {
// types[wrapper::class.java.name] = wrapper.type
// }
//
// }
//
//
// override fun serialize(wrapper: ObjectWrapper<Any?>, type: Type,
// jsonSerializationContext: JsonSerializationContext): JsonElement {
// return jsonSerializationContext.serialize(wrapper, type)
// }
//
// override fun deserialize(jsonElement: JsonElement, type: Type,
// jsonDeserializationContext: JsonDeserializationContext): ObjectWrapper<Any?>? {
//
// try {
// val jsonObj = jsonElement.getAsJsonObject()
// val typeStr = jsonObj.get("type").getAsString()
// val objectType = Class.forName(typeStr)
// val obj: Any?
//// if (typeStr.toLowerCase().contains("resourcemapwrapper")) {
//// println("fdsaf")
//// }
//
// if (jsonObj.get("object").toString().length > 0 && jsonObj.get("object").toString()!="null") {
// if (objectType.superclass == ObjectTypeWrapper::class.java) {
// obj = jsonDeserializationContext.deserialize<Any>(jsonObj.get("object"), types[objectType.name])
// } else {
// obj = jsonDeserializationContext.deserialize<Any>(jsonObj.get("object"), objectType)
// }
// } else {
// obj = null
// }
if (jsonObj.get("object").toString().length > 0 && jsonObj.get("object").toString()!="null") {
if (objectType.superclass == ObjectTypeWrapper::class.java) {
obj = jsonDeserializationContext.deserialize<Any>(jsonObj.get("object"), types[objectType.name])
} else {
obj = jsonDeserializationContext.deserialize<Any>(jsonObj.get("object"), objectType)
}
} else {
obj = null
}
val timeout = jsonObj.get("timeout")?.asLong
return if (timeout != null) {
ObjectWrapper(typeStr, obj, timeout)
} else {
ObjectWrapper(typeStr, obj)
}
} catch (ex: ClassNotFoundException) {
return null //ObjectWrapper(Any::class.java.name, Any()) // null
} catch (ex: NullPointerException) {
return null //ObjectWrapper(Any::class.java.name, Any()) // null
}
}
}
// val timeout = jsonObj.get("timeout")?.asLong
//
// return if (timeout != null) {
// ObjectWrapper(typeStr, obj, timeout)
// } else {
// ObjectWrapper(typeStr, obj)
// }
//
// } catch (ex: ClassNotFoundException) {
//
// return null //ObjectWrapper(Any::class.java.name, Any()) // null
// } catch (ex: NullPointerException) {
// return null //ObjectWrapper(Any::class.java.name, Any()) // null
// }
// }
//}
//
......@@ -3,10 +3,6 @@ package psnc.m2dc.rtm.properties
//TODO: reload ustawien?
import com.casstomdev.appdata.DataExpirationStorage
import com.casstomdev.appdata.IStorage
import com.casstomdev.appdata.StandardSortedMap
import com.casstomdev.appdata.SynchronizedStandardStorage
import com.google.gson.Gson
import com.google.gson.JsonElement
import com.google.gson.JsonObject
......@@ -22,7 +18,6 @@ import psnc.m2dc.rtm.utils.logError
import psnc.m2dc.rtm.utils.printConsole
import java.io.BufferedReader
import java.io.File
import java.io.FileNotFoundException
import java.io.FileReader
import java.lang.StringBuilder
import java.lang.reflect.Type
......@@ -54,20 +49,20 @@ class RTMProperties {
// storage = initStorage(this.getPath(Keys.FileStorage.storage_location, "rtm.json").toString())
}
fun initStorage(path: String?): IStorage<String> {
val newStorage = SynchronizedStandardStorage<String>(
path, psnc.m2dc.rtm.properties.CustomObjectSerializer(), null,
Keys.FileStorage.default_key_timeout.get())
val storage = DataExpirationStorage<String>(300000, StandardSortedMap<String>(300000L, false),
newStorage, DataExpirationStorage.CleanMode.EVENT_BASED)
try {
log.debug("load storage for path: $path")
storage.load()
} catch (ex: FileNotFoundException) {
log.warn("File:$path not found ", ex.message)
}
return storage
}
// fun initStorage(path: String?): IStorage<String> {
// val newStorage = SynchronizedStandardStorage<String>(
// path, psnc.m2dc.rtm.properties.CustomObjectSerializer(), null,
// Keys.FileStorage.default_key_timeout.get())
// val storage = DataExpirationStorage<String>(300000, StandardSortedMap<String>(300000L, false),
// newStorage, DataExpirationStorage.CleanMode.EVENT_BASED)
// try {
// log.debug("load storage for path: $path")
// storage.load()
// } catch (ex: FileNotFoundException) {
// log.warn("File:$path not found ", ex.message)
// }
// return storage
// }
/**
* path to ini file
......
package psnc.m2dc.rtm.rpm
import com.casstomdev.appdata.IStorage
import com.google.gson.JsonArray
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import psnc.m2dc.rtm.dao.ActionCache
import psnc.m2dc.rtm.dao.DAO
import psnc.m2dc.rtm.dao.DataDAO
import psnc.m2dc.rtm.model.rest.ResourceAction
import psnc.m2dc.rtm.model.rest.ResourceActionResult
import psnc.m2dc.rtm.model.rpm.ManagementApi
import psnc.m2dc.rtm.model.rpm.ManagementMethodType
import psnc.m2dc.rtm.model.rpm.Resource
import psnc.m2dc.rtm.model.rpm.SensorMap
import psnc.m2dc.rtm.properties.RTMProperties
import psnc.m2dc.rtm.properties.keys.Keys
import psnc.m2dc.rtm.rpm.nativeapi.*
import psnc.m2dc.rtm.utils.*
import java.lang.IllegalArgumentException
......@@ -545,74 +541,74 @@ printConsole("ipmi")
//</editor-fold>
private fun recsLoadBaseboardData() {
DAO.ResourcesManagerApi.getRecsHosts(true).forEach()
//this.ldapHostList.forEach()
{ host ->
val baseBoards = RECSMonitoringApi.instance.listBaseboards(host)
baseBoards.baseboardList.forEach({ baseBoard ->
var key = DataDAO.getKey(baseBoard.id, ManagementMethodType.power.toString())
var map = this.storage.get<HashMap<String, Float>>(key,
HashMap<String, Float>()) as HashMap<String, Float>
map["current_power_usage"] = baseBoard.infrastructurePower?.toFloat() ?: 0.0f
this.storage.put(key, map, RTMProperties.ONLINE_DATA_TIMEOUT)
key = DataDAO.getKey(baseBoard.id, ManagementMethodType.temperature.toString())
map = this.storage.get<HashMap<String, Float>>(key, HashMap<String, Float>())
baseBoard.temperatures?.forEachIndexed { index, value ->
map["sensor_${index}_temperature"] = value?.toFloat() ?: 0.0f
}
this.storage.put(key, map, RTMProperties.ONLINE_DATA_TIMEOUT)
})
}
}
private fun recsLoadBackplaneData() {
DAO.ResourcesManagerApi.getRecsHosts(true).forEach { host ->
val backplanes = RECSMonitoringApi.instance.listBackplane(host)
backplanes.backplaneList.forEach { backplane ->
val key = DataDAO.getKey(backplane.id, ManagementMethodType.temperature.toString())
val map = this.storage.get<HashMap<String, Float>>(key,
HashMap<String, Float>()) as HashMap<String, Float>
backplane.temperatures?.forEachIndexed { index, value ->
map["sensor_${index}_temperature"] = value?.toFloat() ?: 0.0f
}
this.storage.put(key, map, RTMProperties.ONLINE_DATA_TIMEOUT)
}
}
}
//
// private fun recsLoadBaseboardData() {
// DAO.ResourcesManagerApi.getRecsHosts(true).forEach()
// //this.ldapHostList.forEach()
// { host ->
// val baseBoards = RECSMonitoringApi.instance.listBaseboards(host)
// baseBoards.baseboardList.forEach({ baseBoard ->
// var key = DataDAO.getKey(baseBoard.id, ManagementMethodType.power.toString())
// var map = this.storage.get<HashMap<String, Float>>(key,
// HashMap<String, Float>()) as HashMap<String, Float>
// map["current_power_usage"] = baseBoard.infrastructurePower?.toFloat() ?: 0.0f
// this.storage.put(key, map, RTMProperties.ONLINE_DATA_TIMEOUT)
//
//
// key = DataDAO.getKey(baseBoard.id, ManagementMethodType.temperature.toString())
// map = this.storage.get<HashMap<String, Float>>(key, HashMap<String, Float>())
// baseBoard.temperatures?.forEachIndexed { index, value ->
// map["sensor_${index}_temperature"] = value?.toFloat() ?: 0.0f
// }
// this.storage.put(key, map, RTMProperties.ONLINE_DATA_TIMEOUT)
// })
// }
// }
//
// private fun recsLoadBackplaneData() {
// DAO.ResourcesManagerApi.getRecsHosts(true).forEach { host ->
// val backplanes = RECSMonitoringApi.instance.listBackplane(host)
// backplanes.backplaneList.forEach { backplane ->
// val key = DataDAO.getKey(backplane.id, ManagementMethodType.temperature.toString())
// val map = this.storage.get<HashMap<String, Float>>(key,
// HashMap<String, Float>()) as HashMap<String, Float>
// backplane.temperatures?.forEachIndexed { index, value ->
// map["sensor_${index}_temperature"] = value?.toFloat() ?: 0.0f
// }
// this.storage.put(key, map, RTMProperties.ONLINE_DATA_TIMEOUT)
// }
// }
// }