From 4fdfadb5e02815e04e1d456d05835ce83aa6a1c1 Mon Sep 17 00:00:00 2001 From: ahshahid Date: Wed, 20 Nov 2019 21:32:01 -0800 Subject: [PATCH 001/101] linking store's master --- store | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/store b/store index 4f7bf98e29..cd13561edd 160000 --- a/store +++ b/store @@ -1 +1 @@ -Subproject commit 4f7bf98e296f1b4d03b974d1d35759d48e397145 +Subproject commit cd13561edd92bada628b30b87baf573178c2f7f6 From 461e5a3893b6bacb68ec28614ee57523d4b47d76 Mon Sep 17 00:00:00 2001 From: ahshahid Date: Thu, 21 Nov 2019 15:48:22 -0800 Subject: [PATCH 002/101] linking store with snappydata --- store | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/store b/store index cd13561edd..90ebfaf11f 160000 --- a/store +++ b/store @@ -1 +1 @@ -Subproject commit cd13561edd92bada628b30b87baf573178c2f7f6 +Subproject commit 90ebfaf11fbd9538b6795e5a6197296a1448443a From 5406a0ea93cc472f8ba0dc408e4ed1dfefc0914c Mon Sep 17 00:00:00 2001 From: ahshahid Date: Thu, 21 Nov 2019 16:52:29 -0800 Subject: [PATCH 003/101] linking store --- store | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/store b/store index 90ebfaf11f..f70f4018fa 160000 --- a/store +++ b/store @@ -1 +1 @@ -Subproject commit 90ebfaf11fbd9538b6795e5a6197296a1448443a +Subproject commit f70f4018fae879d4b79c563545c5c9331af54f15 From 2a9b94c926cc1ffbfcd960d9e26f89dbb34042ea Mon Sep 17 00:00:00 2001 From: hemanthmeka <36498621+hemanthmeka@users.noreply.github.com> Date: Fri, 22 Nov 2019 18:22:02 +0530 Subject: [PATCH 004/101] fix for hs error in data extractor (#1480) --- .../spark/sql/execution/oplog/impl/OpLogRdd.scala | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/core/src/main/scala/org/apache/spark/sql/execution/oplog/impl/OpLogRdd.scala b/core/src/main/scala/org/apache/spark/sql/execution/oplog/impl/OpLogRdd.scala index 6a0182e802..aeede74801 100644 --- a/core/src/main/scala/org/apache/spark/sql/execution/oplog/impl/OpLogRdd.scala +++ b/core/src/main/scala/org/apache/spark/sql/execution/oplog/impl/OpLogRdd.scala @@ -16,6 +16,7 @@ */ package org.apache.spark.sql.execution.oplog.impl +import java.nio.ByteBuffer import java.sql.Timestamp import scala.collection.JavaConverters._ @@ -422,7 +423,7 @@ class OpLogRdd( val valueBuffer = value.getValueRetain(FetchRequest.DECOMPRESS).getBuffer val decoder = ColumnEncoding.getColumnDecoder(valueBuffer, field) val valueArray = if (valueBuffer == null || valueBuffer.isDirect) { - null + valueBuffer } else { valueBuffer.array() } @@ -488,7 +489,13 @@ class OpLogRdd( Row.fromSeq(schema.indices.map { colIndx => val decoderAndValue = decodersAndValues(colIndx) val colDecoder = decoderAndValue._1 - val colArray = decoderAndValue._2 + var directBuffer: ByteBuffer = null + val colArray = decoderAndValue._2 match { + case b: ByteBuffer => + directBuffer = b // need reference to directBuffer till we are done reading + null + case arr: Array[Byte] => arr + } val colNextNullPosition = colDecoder.getNextNullPosition val fieldIsNull = rowNum + currentDeleted == colNextNullPosition if (fieldIsNull) { From bdc6591ede810efba77720130facb4469d37d569 Mon Sep 17 00:00:00 2001 From: paresh-p11 <43569032+paresh-p11@users.noreply.github.com> Date: Fri, 22 Nov 2019 18:23:55 +0530 Subject: [PATCH 005/101] Fix SNAP-3238 (#1479) * [SNAP-3238] Fixing logic to choose member object. --- .../cluster/PrimaryDUnitRecoveryTest.scala | 457 ++++++++---------- .../snappydata/recovery/RecoveryService.scala | 179 +++++-- store | 2 +- 3 files changed, 354 insertions(+), 284 deletions(-) diff --git a/cluster/src/dunit/scala/io/snappydata/cluster/PrimaryDUnitRecoveryTest.scala b/cluster/src/dunit/scala/io/snappydata/cluster/PrimaryDUnitRecoveryTest.scala index fd0ce7977f..93148aac8b 100644 --- a/cluster/src/dunit/scala/io/snappydata/cluster/PrimaryDUnitRecoveryTest.scala +++ b/cluster/src/dunit/scala/io/snappydata/cluster/PrimaryDUnitRecoveryTest.scala @@ -30,13 +30,12 @@ import com.pivotal.gemfirexd.Attribute import com.pivotal.gemfirexd.Property.{AUTH_LDAP_SEARCH_BASE, AUTH_LDAP_SERVER} import com.pivotal.gemfirexd.security.{LdapTestServer, SecurityTestUtils} import io.snappydata.test.dunit.{AvailablePortHelper, DistributedTestBase} -import io.snappydata.thrift.internal.ClientClob +import io.snappydata.thrift.internal.{ClientBlob, ClientClob} import org.apache.commons.io.output.TeeOutputStream import org.scalatest.Assertions._ import org.apache.spark.Logging import org.apache.spark.sql.collection.Utils -import org.apache.spark.sql.types.DecimalType import org.apache.spark.sql.udf.UserDefinedFunctionsDUnitTest class PrimaryDUnitRecoveryTest(s: String) extends DistributedTestBase(s) // scalastyle:ignore @@ -98,7 +97,6 @@ class PrimaryDUnitRecoveryTest(s: String) extends DistributedTestBase(s) // scal val workDir = new File(workDirPath) stopCluster() - // TODO: remove the negation below after testing if (test_status) { logInfo("Clearing conf and work dir.") clearDirectory(confDir) @@ -277,7 +275,6 @@ class PrimaryDUnitRecoveryTest(s: String) extends DistributedTestBase(s) // scal workDir.getAbsolutePath } - // todo def renameLater(resultSet: ResultSet, colCount: Int, stringBuilder: StringBuilder, filePathOrg: String): mutable.StringBuilder = { while (resultSet.next()) { @@ -323,20 +320,32 @@ class PrimaryDUnitRecoveryTest(s: String) extends DistributedTestBase(s) // scal stringBuilder.clear() (1 until colCount).foreach(i => { resultSet.getObject(i) match { - case clob: ClientClob => + case clob: ClientClob => { stringBuilder ++= s"${ clob .getSubString(1L, clob.length().toInt) }," + } + case blob: ClientBlob => { + stringBuilder ++= s"${ + scala.io.Source.fromInputStream(resultSet.getBlob(i).getBinaryStream).mkString + }," + } case _ => stringBuilder ++= s"${resultSet.getObject(i)}," } }) resultSet.getObject(colCount) match { - case clob: ClientClob => + case clob: ClientClob => { stringBuilder ++= s"${ clob.getSubString(1L, clob.length().toInt) }" + } + case blob: ClientBlob => { + stringBuilder ++= s"${ + scala.io.Source.fromInputStream(resultSet.getBlob(colCount).getBinaryStream).mkString + }" + } case _ => stringBuilder ++= s"${resultSet.getObject(colCount)}" } @@ -349,19 +358,31 @@ class PrimaryDUnitRecoveryTest(s: String) extends DistributedTestBase(s) // scal stringBuilder.clear() (1 until colCount).foreach(i => { resultSet.getObject(i) match { - case clob: ClientClob => + case clob: ClientClob => { stringBuilder ++= s"${ clob.getSubString(1L, clob.length().toInt) }," + } + case blob: ClientBlob => { + stringBuilder ++= s"${ + scala.io.Source.fromInputStream(resultSet.getBlob(i).getBinaryStream).mkString + }," + } case _ => stringBuilder ++= s"${resultSet.getObject(i)}," } }) resultSet.getObject(colCount) match { - case clob: ClientClob => + case clob: ClientClob => { stringBuilder ++= s"${ clob.getSubString(1L, clob.length().toInt) }" + } + case blob: ClientBlob => { + stringBuilder ++= s"${ + scala.io.Source.fromInputStream(resultSet.getBlob(colCount).getBinaryStream).mkString + }" + } case _ => stringBuilder ++= s"${resultSet.getObject(colCount)}" } @@ -491,44 +512,48 @@ class PrimaryDUnitRecoveryTest(s: String) extends DistributedTestBase(s) // scal val arrBuf: ArrayBuffer[String] = ArrayBuffer.empty var i = 0 + def resetBuffer = { + arrBuf.clear() + i = 0 + } + // todo : Refactor the code. Reuse variables where possible - val rs1 = stmtRec.executeQuery("SELECT * FROM gemfire10.test1coltab1 ORDER BY col1") + var rs = stmtRec.executeQuery("SELECT * FROM gemfire10.test1coltab1 ORDER BY col1") logDebug("=== SELECT * FROM test1coltab1 ===\n") str.clear() - arrBuf.clear() - i = 0 + resetBuffer arrBuf ++= ArrayBuffer("1,aaaa,2.2", "2,bbbb,3.3") - while (rs1.next()) { - assert((s"${rs1.getInt("col1")}," + - s"${rs1.getString("col2")},${rs1.getFloat("col3")}").equalsIgnoreCase(arrBuf(i))) + while (rs.next()) { + assert((s"${rs.getInt("col1")}," + + s"${rs.getString("col2")},${rs.getFloat("col3")}").equalsIgnoreCase(arrBuf(i))) i += 1 } - rs1.close() + rs.close() - val rs5 = stmtRec.executeQuery("SELECT * FROM tapp.test1coltab2") + rs = stmtRec.executeQuery("SELECT * FROM tapp.test1coltab2") logDebug("SELECT * FROM tapp.test1coltab2") str.clear() - while (rs5.next()) { - str ++= s"${rs5.getInt(2)}\t" + while (rs.next()) { + str ++= s"${rs.getInt(2)}\t" } assert(str.toString().length === 0) // empty table - rs5.close() + rs.close() - val rs6 = stmtRec.executeQuery("SELECT * FROM tapp.test1rowtab3") + rs = stmtRec.executeQuery("SELECT * FROM tapp.test1rowtab3") logDebug("SELECT * FROM tapp.test1rowtab3") str.clear() - while (rs6.next()) { // should not go in the loop as the table is empty. - str ++= s"${rs6.getInt(2).toString}" + while (rs.next()) { // should not go in the loop as the table is empty. + str ++= s"${rs.getInt(2).toString}" } assert(str.toString().length === 0) - rs6.close() + rs.close() - var rs2 = stmtRec.executeQuery("show tables in gemfire10") + rs = stmtRec.executeQuery("show tables in gemfire10") logDebug("TableNames in gemfire10:\n") str.clear() - while (rs2.next()) { - tempTab = rs2.getString("tableName") + " " + while (rs.next()) { + tempTab = rs.getString("tableName") + " " logDebug(tempTab) str ++= tempTab } @@ -542,145 +567,143 @@ class PrimaryDUnitRecoveryTest(s: String) extends DistributedTestBase(s) // scal tempStr.contains("TEST1ROWTAB6") && tempStr.contains("VW_TEST1COLTAB1") ) - rs2.close() + rs.close() - rs2 = stmtRec.executeQuery(s"show CREATE TABLE $tempTab") + rs = stmtRec.executeQuery(s"show CREATE TABLE $tempTab") logDebug(s"=== show CREATE TABLE $tempTab") str.clear() - while (rs2.next()) { - str ++= s"${rs2.getString(1)}\t" + while (rs.next()) { + str ++= s"${rs.getString(1)}\t" } //todo need to find a better way to assert the result assert(str.toString().toUpperCase().contains("CREATE ")) - rs2.close() + rs.close() - val rs3 = stmtRec.executeQuery("show tables in tapp") + rs = stmtRec.executeQuery("show tables in tapp") logDebug("\ntableNames in tapp:") str.clear() - while (rs3.next()) { - val c2 = rs3.getString("tableName") + while (rs.next()) { + val c2 = rs.getString("tableName") logDebug(c2) str ++= s"$c2\t" } assert(str.toString().toUpperCase().contains("TEST1COLTAB2") && str.toString().toUpperCase().contains("TEST1ROWTAB3")) - rs3.close() + rs.close() - var rs4 = stmtRec.executeQuery("show functions") + rs = stmtRec.executeQuery("show functions") logInfo("Functions :\n") str.clear() - while (rs4.next()) { - str ++= s"${rs4.getString("function")}\t" + while (rs.next()) { + str ++= s"${rs.getString("function")}\t" } assert(str.toString().toUpperCase().contains("GEMFIRE10.INTUDF1")) - rs4.close() + rs.close() - rs4 = stmtRec.executeQuery(s"select *,intudf1(col2) as newcol from GEMFIRE10.test1coltab1") - if (rs4.next()) { - assert(rs4.getInt("newcol") === 6) + rs = stmtRec.executeQuery(s"select *,intudf1(col2) as newcol from GEMFIRE10.test1coltab1") + if (rs.next()) { + assert(rs.getInt("newcol") === 6) } + rs.close() - rs4 = stmtRec.executeQuery("show schemas") + rs = stmtRec.executeQuery("show schemas") logInfo("=== show schemas ===") str.clear() - while (rs4.next()) { - str ++= s"${rs4.getString("databaseName")}\t" + while (rs.next()) { + str ++= s"${rs.getString("databaseName")}\t" } assert(str.toString().toUpperCase().contains("TAPP") && str.toString().toUpperCase().contains("GEMFIRE10")) - rs4.close() + rs.close() // custom diskstore test - column table - rs4 = stmtRec.executeQuery("SELECT * FROM gemfire10.test1coltab4") - println("SELECT * FROM gemfire10.test1coltab4;") - while (rs4.next()) { - // todo finish this - println(s"${rs4.getInt(2).toString} ${rs4.getInt(2).toString}") + rs = stmtRec.executeQuery("SELECT * FROM gemfire10.test1coltab4") + resetBuffer + arrBuf ++= ArrayBuffer("11,111", "333,33", "11,111", "333,33") + while (rs.next()) { + assert(s"${rs.getInt(1)},${rs.getInt(2)}" === arrBuf(i)) + i += 1 } - rs4.close() + rs.close() // describe table - println("====Describe table - gemfire10.test1coltab4====") - logInfo("====Describe table - gemfire10.test1coltab4====") - rs4 = stmtRec.executeQuery("describe gemfire10.test1coltab4") - arrBuf.clear() - i = 0 + rs = stmtRec.executeQuery("describe gemfire10.test1coltab4") + resetBuffer arrBuf ++= ArrayBuffer("COL1 - int", "COL2 - int") - while (rs4.next()) { - assert(s"${rs4.getString(1)} - ${rs4.getString(2)}".equalsIgnoreCase(arrBuf(i))) + while (rs.next()) { + assert(s"${rs.getString(1)} - ${rs.getString(2)}".equalsIgnoreCase(arrBuf(i))) i += 1 } - rs4.close() + rs.close() // query view - rs4 = stmtRec.executeQuery("select col1,* from gemfire10.vw_test1coltab1 ORDER BY 1") - println("=== view : vw_test1coltab1===") - arrBuf.clear() - i = 0 + rs = stmtRec.executeQuery("select col1,* from gemfire10.vw_test1coltab1 ORDER BY 1") + resetBuffer arrBuf ++= ArrayBuffer("1,1,aaaa,2.200000000000000000", "2,2,bbbb,3.300000000000000000") - while (rs4.next()) { - assert(s"${rs4.getInt(1)},${rs4.getInt(2)},${rs4.getString(3)},${rs4.getBigDecimal(4)}" + while (rs.next()) { + assert(s"${rs.getInt(1)},${rs.getInt(2)},${rs.getString(3)},${rs.getBigDecimal(4)}" .equalsIgnoreCase(arrBuf(i))) i += 1 } - rs4.close() + rs.close() + // custom diskstore test - row row table - var rstest1rowtab5 = stmtRec.executeQuery("SELECT * FROM gemfire10.test1rowtab5") - println("SELECT * FROM gemfire10.test1rowtab5;") - while (rstest1rowtab5.next()) { - println(s"row : ${rstest1rowtab5.getInt(1)} ${rstest1rowtab5.getString(2)}") + rs = stmtRec.executeQuery("SELECT * FROM gemfire10.test1rowtab5 ORDER BY 1") + arrBuf ++= ArrayBuffer("111,adsf", "111,adsf", "111,adsf", "2223,zxcvxcv", "2223,zxcvxcv", "2223,zxcvxcv") + while (rs.next()) { + assert(s"${rs.getInt(1)},${rs.getString(2)}" === arrBuf(i)) + i += 1 } - rstest1rowtab5.close() + rs.close() - rs4 = stmtRec.executeQuery("select col1, col2, col3, col4, col5 from gemfire10" + - ".test1rowtab6 order by col4") - println("==== test1rowtab6 ====") + rs = stmtRec.executeQuery("SELECT col1, col2, col3, col4, col5 from gemfire10" + + ".test1rowtab6 ORDER BY col4") arrBuf.clear() i = 0 arrBuf ++= ArrayBuffer("NULL,NULL,333.333,NULL,true", "NULL,xczadsf,232.1222,11,NULL", "NULL,adsf,NULL,12,false") - while (rs4.next()) { + while (rs.next()) { str.clear() - str ++= s"${rs4.getObject(1)},${rs4.getString(2)},${rs4.getObject(3)}" + - s",${rs4.getObject(4)},${rs4.getObject(5)}" + str ++= s"${rs.getObject(1)},${rs.getString(2)},${rs.getObject(3)}" + + s",${rs.getObject(4)},${rs.getObject(5)}" assert(str.toString().toUpperCase() === (arrBuf(i)).toUpperCase()) i += 1 } - rs4.close() + rs.close() - rs4 = stmtRec.executeQuery("select col1, col2, col3, col4, col5 from" + + rs = stmtRec.executeQuery("select col1, col2, col3, col4, col5 from" + " gemfire10.test1coltab7 ORDER BY col1") arrBuf.clear() i = 0 arrBuf ++= ArrayBuffer("NULL,qewrqewr4,345.123324,11,2019-03-21", "8123372036812312307,asdfwerq334,NULL,NULL,NULL", "9123372036812312307,asdfwerq334,123.123324,12,2019-03-20") - while (rs4.next()) { + while (rs.next()) { str.clear() - str ++= s"${rs4.getObject(1)},${rs4.getObject(2)},${rs4.getObject(3)}," + - s"${rs4.getObject(4)},${rs4.getObject(5)}" + str ++= s"${rs.getObject(1)},${rs.getObject(2)},${rs.getObject(3)}," + + s"${rs.getObject(4)},${rs.getObject(5)}" assert(str.toString().toUpperCase() === (arrBuf(i)).toUpperCase()) i += 1 } - rs4.close() + rs.close() - rs4 = stmtRec.executeQuery("SELECT * FROM gemfire10.test1coltab8 ORDER BY col1") + rs = stmtRec.executeQuery("SELECT * FROM gemfire10.test1coltab8 ORDER BY col1") arrBuf.clear() i = 0 arrBuf ++= ArrayBuffer("null,null,null,null,null", "8123372036812312307,qewrwr4,345.123324,11,2019-03-21", "9123372036812312307,null,123.123324,12,null") - while (rs4.next()) { + while (rs.next()) { str.clear() - str ++= s"${rs4.getObject(1)},${rs4.getObject(2)},${rs4.getObject(3)}," + - s"${rs4.getObject(4)},${rs4.getObject(5)}" + str ++= s"${rs.getObject(1)},${rs.getObject(2)},${rs.getObject(3)}," + + s"${rs.getObject(4)},${rs.getObject(5)}" assert(str.toString().toUpperCase() === (arrBuf(i)).toUpperCase()) i += 1 } - rs4.close() + rs.close() stmtRec.execute("call sys.EXPORT_DDLS('./recover_ddls_test1/');") @@ -704,7 +727,7 @@ class PrimaryDUnitRecoveryTest(s: String) extends DistributedTestBase(s) // scal // Focused particularly on checking if all data types can be // extracted properly // check for row and column type - logInfo(s"PP ____ recovery_mode_dir: $recovery_mode_dir") + logDebug(s"Recovery_mode_dir: $recovery_mode_dir") // TODO:Paresh: following tests can be clubbed/rearranged later. Increase the data volume later confDirPath = createConfDir("test3") val leadsNum = 1 @@ -750,15 +773,15 @@ class PrimaryDUnitRecoveryTest(s: String) extends DistributedTestBase(s) // scal col7 byte NOT NULL, c1 tinyint NOT NULL, c2 varchar(22) NOT NULL, c3 string NOT NULL, c5 boolean NOT NULL,c6 double NOT NULL, c8 timestamp NOT NULL, c9 date NOT NULL, c10 decimal(15,5) NOT NULL, c11 numeric(20,10) NOT NULL, - c12 float NOT NULL,c13 real not null) USING COLUMN + c12 float NOT NULL,c13 real not null, c14 binary, c15 blob, c16 clob) USING COLUMN OPTIONS (BUCKETS '5', COLUMN_MAX_DELTA_ROWS '135'); """) stmt.execute( - s"""INSERT INTO gemfire10.test3tab1 VALUES(9123372036854775807,2117483647,2116483647, + s"""INSERT INTO gemfire10.test3tab1 select 9123372036854775807,2117483647,2116483647, 8223372036854775807,72,13,5,5,'qwerqwerqwer','qewrqewr',false,912384020490234.91928374997239749824, '2019-02-18 15:31:55.333','2019-02-18',2233.67234,4020490234.7239749824, - 912384020490234.91928374997239749824,920490234.9192837499724)""".stripMargin) + 912384020490234.91928374997239749824,920490234.9192837499724, cast ('aaa' as binary), cast('2234' as blob), cast('adsf' as clob)""".stripMargin) stmt.execute("INSERT INTO gemfire10.test3tab1 select id*100000000000000,id,id*100000000" + ",id*100000000000000,id,id, cast(id as byte), cast(id as tinyint)" + @@ -766,10 +789,8 @@ class PrimaryDUnitRecoveryTest(s: String) extends DistributedTestBase(s) // scal ", cast(id%2 as Boolean), cast((id*701*7699 + id*1342341*2267)/2 as double)" + ", CURRENT_TIMESTAMP, CURRENT_DATE, cast(id*241/11 as Decimal(15,5))" + ", cast(id*701/11 as Numeric(20,10)), cast(concat(id*100,'.',(id+1)*7699) as float)" + - ", cast(concat(id*100000000000,'.',(id+1)*2267*7699) as real) from range(500);") + ", cast(concat(id*100000000000,'.',(id+1)*2267*7699) as real), cast('binary_'|| id as binary), cast('blob_' || id as blob), cast(id*2 as clob) from range(500);") - - // todo: add not null here AND add binary and blob val rsTest3tab1 = stmt.executeQuery("SELECT * FROM gemfire10.test3tab1 ORDER BY col2") compareResultSet("gemfire10.test3tab1", rsTest3tab1, false) @@ -828,13 +849,16 @@ class PrimaryDUnitRecoveryTest(s: String) extends DistributedTestBase(s) // scal cast('yyyy' as blob) from range(5); """.stripMargin) -// val rsTest3Reptab2 = stmt.executeQuery("SELECT * FROM gemfire10.test3Reptab2 ORDER BY col2") -// compareResultSet("gemfire10.test3Reptab2", rsTest3Reptab2, false) + val rsTest3Reptab2 = stmt.executeQuery("SELECT * FROM gemfire10.test3Reptab2 ORDER BY col2") + compareResultSet("gemfire10.test3Reptab2", rsTest3Reptab2, isRecoveredDataRS = false) // enable once support is added for primary key and binary,clob,blob // 3. Random mix n match data types stmt.execute("CREATE TABLE gemfire10.test3tab3 (col1 binary, col2 clob, col3 blob, col4 varchar(44), col5 int, primary key (col5)) using row") stmt.execute("INSERT INTO gemfire10.test3tab3 select cast('a' as binary), cast('b' as clob), cast('1' as blob), 'adsf', 123") + stmt.execute("INSERT INTO gemfire10.test3tab3 select cast('aa' as binary), cast('bb' as clob), cast('11' as blob), 'adsfg', 1234") + stmt.execute("INSERT INTO gemfire10.test3tab3 select cast('aaa' as binary), cast('bbb' as clob), cast('1111' as blob), 'adsfgh', 12345") + stmt.execute("INSERT INTO gemfire10.test3tab3 select cast('asdf' as binary), cast('bnm' as clob), cast('1111111' as blob), 'adsfghi', 123456") // with option - key_columns stmt.execute("CREATE TABLE test3coltab4 (col1 int, col2 string, col3 float) USING COLUMN" + @@ -842,9 +866,8 @@ class PrimaryDUnitRecoveryTest(s: String) extends DistributedTestBase(s) // scal stmt.execute("INSERT INTO test3coltab4 VALUES(1,'aaa',123.122)") stmt.execute("INSERT INTO test3coltab4 VALUES(2,'bbb',4444.55)") - // row table - not null columns todo: add not null here - stmt.execute("CREATE TABLE test3rowtab5 (col1 FloaT, col2 TIMEstamp, col3 BOOLEAN ," + - " col4 varchar(1) , col5 integer ) using row") + stmt.execute("CREATE TABLE test3rowtab5 (col1 FloaT NOT NULL, col2 TIMEstamp NOT NULL, col3 BOOLEAN NOT NULL," + + " col4 varchar(1) NOT NULL, col5 integer NOT NULL) using row") stmt.execute("INSERT INTO test3rowtab5 VALUES(123.12321, '2019-02-18 15:31:55.333', 0, 'a',12)") stmt.execute("INSERT INTO test3rowtab5 VALUES(222.12321, '2019-02-18 16:31:56.333', 0, 'b',13)") stmt.execute("INSERT INTO test3rowtab5 VALUES(3333.12321, '2019-02-18 17:31:57.333', 'true', 'c',14)") @@ -865,20 +888,6 @@ class PrimaryDUnitRecoveryTest(s: String) extends DistributedTestBase(s) // scal stmt.execute("INSERT INTO test3coltab7 VALUES(1012.312321314, 4124.1234341," + " 333471498234123, '2019-03-18', 'adfcdefg')") - - val rs71 = stmt.executeQuery("SELECT * FROM gemfire10.test3coltab7 ORDER BY col3;") -// arrBuf.clear() -// i = 0 -// -// arrBuf ++= ArrayBuffer("891012.312321314,1434124.125,193471498234123,2019-02-18,ZXcabcdefg", -// "91012.312321314,34124.125,243471498234123,2019-04-18,qewrabcdefg", -// "1012.312321314,4124.1234341,333471498234123,2019-03-18,adfcdefg") - while (rs71.next()) { - println(s"${rs71.getBigDecimal(2)},${rs71.getDouble(2)},${rs71.getFloat(2)}") - } - rs71.close() - - // todo: Paresh: the peculiar case stmt.execute("CREATE TABLE test3rowtab8 (col1 string, col2 int, col3 varchar(33)," + " col4 boolean, col5 float)using row") @@ -927,6 +936,7 @@ class PrimaryDUnitRecoveryTest(s: String) extends DistributedTestBase(s) // scal // todo: alter table -add/drop column- + stmt.close() conn.close() @@ -939,202 +949,159 @@ class PrimaryDUnitRecoveryTest(s: String) extends DistributedTestBase(s) // scal var str = new mutable.StringBuilder() val arrBuf: ArrayBuffer[String] = ArrayBuffer.empty var i = 0 + + def resetBuffer = { + arrBuf.clear() + i = 0 + } connRec = getConn(locNetPort, "gemfire10", "gemfire10") stmtRec = connRec.createStatement() - var rs1 = stmtRec.executeQuery("SELECT * FROM gemfire10.test3tab1 where col1 = 9123372036854775807") - - if (rs1.next()) { - assert(rs1.getLong(1) === 9123372036854775807L) - assert(rs1.getInt(2) === 2117483647) - assert(rs1.getInt(3) === 2116483647) - assert(rs1.getLong(4) === 8223372036854775807L) - assert(rs1.getShort(5) === 72) - assert(rs1.getShort(6) === 13) - assert(rs1.getByte(7) === 5) - assert(rs1.getByte(8) === 5) - assert(rs1.getString(9) === "qwerqwerqwer") - assert(rs1.getString(10) === "qewrqewr") - assert(rs1.getBoolean(11) === false) - assert(rs1.getDouble(12) === 912384020490234.91928374997239749824) - assert(rs1.getTimestamp(13) === Timestamp.valueOf("2019-02-18 15:31:55.333")) - assert(rs1.getDate(14).toString === "2019-02-18") - assert(rs1.getBigDecimal(15).toString === "2233.67234") - assert(rs1.getBigDecimal(16).toString === "4020490234.7239749824") - assert(rs1.getFloat(17) === "912384020490234.91928374997239749824".toFloat) - assert(rs1.getFloat(18) === "920490234.9192837499724".toFloat) - } - rs1.close() - - rs1 = stmtRec.executeQuery("SELECT * FROM gemfire10.test3tab1 ORDER BY col2") - compareResultSet("gemfire10.test3tab1", rs1, true) - rs1.close() - - - var rs2 = stmtRec.executeQuery("SELECT * FROM gemfire10.test3tab2 where col1 = 9123372036854775807") - if (rs2.next()) { - assert(rs2.getLong(1) === 9123372036854775807L) - assert(rs2.getInt(2) === 2117483647) - assert(rs2.getInt(3) === 2116483647) - assert(rs2.getLong(4) === 8223372036854775807L) - assert(rs2.getShort(5) === 72) - assert(rs2.getShort(6) === 13) - assert(rs2.getByte(7) === 5) - assert(rs2.getByte(8) === 5) - assert(rs2.getString(9) === "qwerqwerqwer") - assert(rs2.getString(10) === "qewrqewr") - assert(rs2.getBoolean(11) === false) - assert(rs2.getDouble(12) === 912384020490234.91928374997239749824) - assert(rs2.getTimestamp(13) === - Timestamp.valueOf("2019-02-18 15:31:55.333")) - assert(rs2.getDate(14).toString === "2019-02-18") - assert(rs2.getBigDecimal(15).toString === "2233.67234") - assert(rs2.getBigDecimal(16).toString === "4020490234.7239749824") - assert(rs2.getFloat(17) === "912384020490234.91928374997239749824".toFloat) - assert(rs2.getFloat(18) === "920490234.9192837499724".toFloat) - } - rs2.close() + var rs = stmtRec.executeQuery("SELECT * FROM gemfire10.test3tab1 ORDER BY col2") + compareResultSet("gemfire10.test3tab1", rs, true) + rs.close() - rs2 = stmtRec.executeQuery("SELECT * FROM gemfire10.test3tab2 ORDER BY col2") - compareResultSet("gemfire10.test3tab2", rs2, true) - rs2.close() + rs = stmtRec.executeQuery("SELECT * FROM gemfire10.test3tab2 ORDER BY col2") + compareResultSet("gemfire10.test3tab2", rs, true) + rs.close() - val rs3 = stmtRec.executeQuery("select col1, col2, col3, col4," + + rs = stmtRec.executeQuery("select col1, col2, col3, col4," + " col5 from gemfire10.test3tab3 ORDER BY col5") + println("select * from test3tab3 =======================") + resetBuffer - while (rs3.next()) { + arrBuf ++= ArrayBuffer("a,b,1,adsf,123", "aa,bb,11,adsfg,1234", "aaa,bbb,1111,adsfgh,12345", "asdf,bnm,1111111,adsfghi,123456") + while (rs.next()) { // scalastyle:off println - println(s"${rs3.getBlob(1)},${rs3.getClob(2)},${rs3.getBlob(3)}," + - s"${rs3.getString(4)},${rs3.getInt(5)}") + println(s"${rs.getBlob(1)},${rs.getClob(2)},${rs.getBlob(3)}," + + s"${rs.getString(4)},${rs.getInt(5)}") + assert(s"${scala.io.Source.fromInputStream(rs.getBlob(1).getBinaryStream).mkString}," + + s"${scala.io.Source.fromInputStream(rs.getClob(2).getAsciiStream).mkString}," + + s"${scala.io.Source.fromInputStream(rs.getBlob(3).getBinaryStream).mkString}," + + s"${rs.getString(4)},${rs.getInt(5)}" == arrBuf(i)) + i += 1 } - val rs4 = stmtRec.executeQuery("select col1, col2, col3 from" + + rs = stmtRec.executeQuery("select col1, col2, col3 from" + " gemfire10.test3coltab4 ORDER BY col1") - arrBuf.clear() - i = 0 + resetBuffer arrBuf ++= ArrayBuffer("1,aaa,123.122", "2,bbb,4444.55") - while (rs4.next()) { - assert(s"${rs4.getInt("col1")},${rs4.getString("col2")},${rs4.getFloat("col3")}" + while (rs.next()) { + assert(s"${rs.getInt("col1")},${rs.getString("col2")},${rs.getFloat("col3")}" .equalsIgnoreCase(arrBuf(i))) i += 1 } assert(i != 0) - rs4.close() + rs.close() - val rs5 = stmtRec.executeQuery("SELECT col1, col2, col3 from gemfire10.test3coltab6 ORDER BY col1") + rs = stmtRec.executeQuery("SELECT col1, col2, col3 from gemfire10.test3coltab6 ORDER BY col1") arrBuf.clear() i = 0 arrBuf ++= ArrayBuffer("100000000000001,5,true", "200000000000001,4,true", "300000000000001,3,false") - while (rs5.next()) { - assert(s"${rs5.getLong("col1")},${rs5.getShort("col2")},${rs5.getBoolean("col3")}" + while (rs.next()) { + assert(s"${rs.getLong("col1")},${rs.getShort("col2")},${rs.getBoolean("col3")}" .equalsIgnoreCase(arrBuf(i)), - s"Got: ${rs5.getLong("col1")}, ${rs5.getShort("col2")}," + - s" ${rs5.getBoolean("col3")}\nExpected: ${arrBuf(i)}") + s"Got: ${rs.getLong("col1")}, ${rs.getShort("col2")}," + + s" ${rs.getBoolean("col3")}\nExpected: ${arrBuf(i)}") i += 1 } assert(i != 0) - rs5.close() + rs.close() - var rs6 = stmtRec.executeQuery("select count(*) rcount, c5 from gemfire10.test3tab1" + + rs = stmtRec.executeQuery("select count(*) rcount, c5 from gemfire10.test3tab1" + " group by c5 having c5 = true ORDER BY c5;") str.clear() - while (rs6.next()) { - str ++= s"${rs6.getInt("rcount")},${rs6.getBoolean("c5")}" + while (rs.next()) { + str ++= s"${rs.getInt("rcount")},${rs.getBoolean("c5")}" } assert(str.toString().equalsIgnoreCase("250,true")) - rs6.close() + rs.close() // 4. Test if all sql functions are working fine - like min,max,avg,etc. // Test if individual columns can be queried - var rs7 = stmtRec.executeQuery("select first(col3) as fCol3, max(col1) as maxCol1," + + rs = stmtRec.executeQuery("select first(col3) as fCol3, max(col1) as maxCol1," + " round(avg(col1)) as avgRoundRes, count(*) as count,concat('str_',first(col4)) as" + " concatRes, cast(first(col1) as string) as castRes, isnull(max(col5)) as isNullRes," + " Current_Timestamp, day(current_timestamp) from gemfire10.test3rowtab5;") - assert(rs7.next() === true) - assert(rs7.getFloat("maxcol1") === 3333.1233F && rs7.getInt("count") === 3) + assert(rs.next() === true) + assert(rs.getFloat("maxcol1") === 3333.1233F && rs.getInt("count") === 3) - rs7.close() + rs.close() -// rs7 = stmtRec.executeQuery("SELECT * FROM gemfire10.test3Reptab2 ORDER BY col2;") -// compareResultSet("gemfire10.test3Reptab2", rs7, true) -// rs7.close() + rs = stmtRec.executeQuery("SELECT * FROM gemfire10.test3Reptab2 ORDER BY col2;") + compareResultSet("gemfire10.test3Reptab2", rs, true) + rs.close() - rs7 = stmtRec.executeQuery("SELECT * FROM gemfire10.test3coltab7 ORDER BY col3;") - arrBuf.clear() - i = 0 + rs = stmtRec.executeQuery("SELECT * FROM gemfire10.test3coltab7 ORDER BY col3;") + resetBuffer arrBuf ++= ArrayBuffer("891012.312321314,1434124.125,193471498234123,2019-02-18,ZXcabcdefg", "91012.312321314,34124.125,243471498234123,2019-04-18,qewrabcdefg", "1012.312321314,4124.12353515625,333471498234123,2019-03-18,adfcdefg") - while (rs7.next()) { - assert(s"${rs7.getBigDecimal(1)},${rs7.getDouble(2)}" + - s",${rs7.getLong(3)},${rs7.getDate(4)},${rs7.getString(5)}" === arrBuf(i)) + while (rs.next()) { + assert(s"${rs.getBigDecimal(1)},${rs.getDouble(2)}" + + s",${rs.getLong(3)},${rs.getDate(4)},${rs.getString(5)}" === arrBuf(i)) i += 1 } assert(i != 0) - rs7.close() + rs.close() + + rs = stmtRec.executeQuery("SELECT * FROM gemfire10.test3rowtab8 ORDER BY col2;") + resetBuffer + arrBuf ++= ArrayBuffer("qewradfs,111,asdfqewr,true,123.1234", + "adsffs,222,vzxcqewr,true,4745.345", "xzcvadfs,444,zxcvzv,false,78768.34") + while (rs.next()) { + assert(s"${rs.getString(1)},${rs.getInt(2)},${rs.getString(3)}," + + s"${rs.getBoolean(4)},${rs.getFloat(5)}" === arrBuf(i)) + i += 1 + } + assert(i != 0) + rs.close() -// rs7 = stmtRec.executeQuery("SELECT * FROM gemfire10.test3rowtab8 ORDER BY col2;") -// arrBuf.clear() -// i = 0 -// arrBuf ++= ArrayBuffer("qewradfs,111,asdfqewr,true,123.1234", -// "adsffs,222,vzxcqewr,true,4745.345345", "xzcvadfs,444,zxcvzv,false,78768.34") -// while (rs7.next()) { -// assert(s"${rs7.getString(1)},${rs7.getInt(2)},${rs7.getString(3)}," + -// s"${rs7.getBoolean(4)},${rs7.getDouble(5)}" === arrBuf(i)) -// i += 1 -// } -// assert(i != 0) -// rs7.close() - - rs7 = stmtRec.executeQuery("SELECT * FROM gemfire10.test3rowtab9 ORDER BY col2;") - arrBuf.clear() - i = 0 + rs = stmtRec.executeQuery("SELECT * FROM gemfire10.test3rowtab9 ORDER BY col2;") + resetBuffer arrBuf ++= ArrayBuffer("null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null") - while (rs7.next()) { - assert(s"${rs7.getObject(1)},${rs7.getObject(2)},${rs7.getObject(3)},${rs7.getObject(4)}," + - s"${rs7.getObject(5)},${rs7.getObject(6)},${rs7.getObject(7)},${rs7.getObject(8)}," + - s"${rs7.getObject(9)},${rs7.getObject(10)},${rs7.getObject(11)}," + - s"${rs7.getObject(12)},${rs7.getObject(13)},${rs7.getObject(14)}," + - s"${rs7.getObject(15)},${rs7.getObject(16)},${rs7.getObject(17)}," + - s"${rs7.getObject(18)}" === arrBuf(i)) + while (rs.next()) { + assert(s"${rs.getObject(1)},${rs.getObject(2)},${rs.getObject(3)},${rs.getObject(4)}," + + s"${rs.getObject(5)},${rs.getObject(6)},${rs.getObject(7)},${rs.getObject(8)}," + + s"${rs.getObject(9)},${rs.getObject(10)},${rs.getObject(11)}," + + s"${rs.getObject(12)},${rs.getObject(13)},${rs.getObject(14)}," + + s"${rs.getObject(15)},${rs.getObject(16)},${rs.getObject(17)}," + + s"${rs.getObject(18)}" === arrBuf(i)) i += 1 } assert(i != 0) - rs7.close() + rs.close() - rs7 = stmtRec.executeQuery("SELECT * FROM gemfire10.test3coltab10 ORDER BY col2;") - arrBuf.clear() - i = 0 + rs = stmtRec.executeQuery("SELECT * FROM gemfire10.test3coltab10 ORDER BY col2;") + resetBuffer arrBuf ++= ArrayBuffer("null,null,null,null,null,null,null,null,null,null,null,null,null" + ",null,null,null,null,null", "null,null,null,null,null,null,null,null,null,null,null," + "null,null,null,null,null,null,null", "null,null,null,null,null,null,null,null,null," + "null,null,null,null,null,null,null,null,null") - while (rs7.next()) { - assert(s"${rs7.getObject(1)},${rs7.getObject(2)},${rs7.getObject(3)},${rs7.getObject(4)}," + - s"${rs7.getObject(5)},${rs7.getObject(6)},${rs7.getObject(7)},${rs7.getObject(8)}," + - s"${rs7.getObject(9)},${rs7.getObject(10)},${rs7.getObject(11)}," + - s"${rs7.getObject(12)},${rs7.getObject(13)},${rs7.getObject(14)}," + - s"${rs7.getObject(15)},${rs7.getObject(16)},${rs7.getObject(17)}," + - s"${rs7.getObject(18)}" === arrBuf(i)) + while (rs.next()) { + assert(s"${rs.getObject(1)},${rs.getObject(2)},${rs.getObject(3)},${rs.getObject(4)}," + + s"${rs.getObject(5)},${rs.getObject(6)},${rs.getObject(7)},${rs.getObject(8)}," + + s"${rs.getObject(9)},${rs.getObject(10)},${rs.getObject(11)}," + + s"${rs.getObject(12)},${rs.getObject(13)},${rs.getObject(14)}," + + s"${rs.getObject(15)},${rs.getObject(16)},${rs.getObject(17)}," + + s"${rs.getObject(18)}" === arrBuf(i)) i += 1 } assert(i != 0) - rs7.close() - - - // is fixed. - null comes out as 0 for few datatypesin recovery mode + rs.close() stmtRec.execute("call sys.EXPORT_DDLS('./recover_ddls_test3/');") stmtRec.close() conn.close() afterEach() test_status = true + } catch { case e: Throwable => afterEach() @@ -1605,7 +1572,7 @@ class PrimaryDUnitRecoveryTest(s: String) extends DistributedTestBase(s) // scal // ********************************************* // ******************testcase 1***************** // ********************************************* - val rs1 = stmtRec.executeQuery("select * from gemfire10.t1") + val rs = stmtRec.executeQuery("select * from gemfire10.t1") val expectedResult1: ListBuffer[Array[Any]] = ListBuffer( Array(1, 111111111111111111.11111111111111111111, 11), Array(2, 222222222222222222.22222222222222222222, null), @@ -1613,8 +1580,8 @@ class PrimaryDUnitRecoveryTest(s: String) extends DistributedTestBase(s) // scal Array(4, 422222222222222222.22222222222222222222, null) ) compareResult(expectedResult1, - getRecFromResultSet(rs1, "integer,double,integer")) - rs1.close() + getRecFromResultSet(rs, "integer,double,integer")) + rs.close() // testcase 2 val rs2 = stmtRec.executeQuery("select * from gemfire10.t2") diff --git a/core/src/main/scala/io/snappydata/recovery/RecoveryService.scala b/core/src/main/scala/io/snappydata/recovery/RecoveryService.scala index 999ac989e3..4b4f085308 100644 --- a/core/src/main/scala/io/snappydata/recovery/RecoveryService.scala +++ b/core/src/main/scala/io/snappydata/recovery/RecoveryService.scala @@ -19,6 +19,7 @@ package io.snappydata.recovery import java.util.function.BiConsumer + import com.pivotal.gemfirexd.internal.engine.ui.{SnappyExternalTableStats, SnappyIndexStats, SnappyRegionStats} import com.gemstone.gemfire.distributed.internal.membership.InternalDistributedMember import com.gemstone.gemfire.internal.cache.PartitionedRegionHelper @@ -27,7 +28,7 @@ import com.pivotal.gemfirexd.Attribute import com.pivotal.gemfirexd.internal.engine.ddl.{DDLConflatable, GfxdDDLQueueEntry, GfxdDDLRegionQueue} import com.pivotal.gemfirexd.internal.engine.distributed.RecoveryModeResultCollector import com.pivotal.gemfirexd.internal.engine.distributed.message.PersistentStateInRecoveryMode -import com.pivotal.gemfirexd.internal.engine.distributed.message.PersistentStateInRecoveryMode.RecoveryModePersistentView +import com.pivotal.gemfirexd.internal.engine.distributed.message.PersistentStateInRecoveryMode.{RecoveryModePersistentView, RecoveryModePersistentViewPair} import com.pivotal.gemfirexd.internal.engine.sql.execute.RecoveredMetadataRequestMessage import scala.collection.JavaConverters.asScalaBufferConverter import scala.collection.mutable @@ -251,9 +252,19 @@ object RecoveryService extends Logging { ddlBuffer } - /* fqtn and bucket number for PR r Column table, -1 indicates replicated row table */ - def getExecutorHost(fqtn: String, bucketId: Int = -1): Seq[String] = { - // Expecting table in the format fqtn i.e. schemaname.tablename + def getColRegionPath(schemaName: String, tableName: String, bucketNumber: Int): String = { + val internalFQTN = schemaName + '.' + Constant.SHADOW_SCHEMA_NAME_WITH_SEPARATOR + + tableName + Constant.SHADOW_TABLE_SUFFIX + + if (Misc.getRegionPath(internalFQTN.toUpperCase) == null) { + throw new IllegalStateException(s"regionPath for $internalFQTN not found") + } else { + val regionPath = Misc.getRegionPath(internalFQTN.toUpperCase) + s"/_PR//B_${regionPath.substring(1, regionPath.length - 1)}/_${bucketNumber}" + } + } + + def getRowRegionPath(fqtn: String, bucketId: Int): String = { val schemaName = fqtn.split('.')(0) val tableName = fqtn.split('.')(1) val replicated = isReplicated(schemaName, tableName) @@ -264,31 +275,43 @@ object RecoveryService extends Logging { val bucketName = PartitionedRegionHelper.getBucketName(tablePath, bucketId) bucketPath = s"/${PartitionedRegionHelper.PR_ROOT_REGION_NAME}/$bucketName" } + bucketPath + } + + /* fqtn and bucket number for PR r Column table, -1 indicates replicated row table */ + def getExecutorHost(fqtn: String, bucketId: Int = -1): Seq[String] = { + val rowRegionPath = getRowRegionPath(fqtn, bucketId) // for null region maps select random host - if (regionViewSortedSet.contains(bucketPath)) { - val hosts = regionViewSortedSet(bucketPath).map(e => { - val hostCanonical = e.getExecutorHost - val host = hostCanonical.split('(').head - s"executor_${host}_$hostCanonical" - }).toSeq - if (hosts.isEmpty) hosts else Seq(hosts.last) + val rowRegionPathKey = combinedViewsMapSortedSet.keySet.filter(_.contains(rowRegionPath + "#$")) + + if (rowRegionPathKey.size != 0) { + assert(rowRegionPathKey.size == 1, s"combinedViewsMapSortedSet should not contain multiple entries for the key $rowRegionPath") + val viewPair = combinedViewsMapSortedSet(rowRegionPathKey.head).lastKey + val hostCanonical = viewPair.getRowView.getExecutorHost + val host = hostCanonical.split('(').head + logDebug(s"Host chosen for bucket : ${rowRegionPathKey.head} :" + + s" ${Seq(s"executor_${host}_$hostCanonical")}") + Seq(s"executor_${host}_$hostCanonical") } else { logWarning(s"Preferred host is not found for bucket id: $bucketId. " + - s"Choosing random host for $bucketPath") + s"Choosing random host for $rowRegionPath") getRandomExecutorHost } } def getRandomExecutorHost: Seq[String] = { - val e = Random.shuffle(regionViewSortedSet.toList).head._2.firstKey + val e = Random.shuffle(regionViewMapSortedSet.toList).head._2.firstKey val hostCanonical = e.getExecutorHost val host = hostCanonical.split('(').head Seq(s"executor_${host}_$hostCanonical") } - val regionViewSortedSet: mutable.Map[String, + val regionViewMapSortedSet: mutable.Map[String, mutable.SortedSet[RecoveryModePersistentView]] = mutable.Map.empty + val combinedViewsMapSortedSet: mutable.Map[String, + mutable.SortedSet[RecoveryModePersistentViewPair]] = mutable.Map.empty + var locatorMember: InternalDistributedMember = _ val persistentObjectMemberMap: mutable.Map[ InternalDistributedMember, PersistentStateInRecoveryMode] = mutable.Map.empty @@ -434,50 +457,43 @@ object RecoveryService extends Logging { val msg = new RecoveredMetadataRequestMessage(collector) msg.executeFunction() val persistentData = collector.getResult - logDebug(s"Number of PersistentStateInRecoveryMode received" + - s" from members: ${persistentData.size()}") + logDebug(s" Total Number of PersistentStateInRecoveryMode objects received ${persistentData.size()}") val itr = persistentData.iterator() while (itr.hasNext) { - val persistentViewObj = itr.next().asInstanceOf[PersistentStateInRecoveryMode] - logInfo(s"PP:PersistentStateInRecoveryMode : $persistentViewObj") - locatorMember = if (persistentViewObj.getMember.getVmKind == - DistributionManager.LOCATOR_DM_TYPE && locatorMember == null) persistentViewObj.getMember else locatorMember - persistentObjectMemberMap += persistentViewObj.getMember -> persistentViewObj - val regionItr = persistentViewObj.getAllRegionViews.iterator() + val persistentStateObj = itr.next().asInstanceOf[PersistentStateInRecoveryMode] + locatorMember = if (persistentStateObj.getMember.getVmKind == + DistributionManager.LOCATOR_DM_TYPE && locatorMember == null) { + persistentStateObj.getMember + } + else if (persistentStateObj.getMember.getVmKind == + DistributionManager.LOCATOR_DM_TYPE && locatorMember != null) { + persistentStateObj.getMember + } + else { + locatorMember + } + persistentObjectMemberMap += persistentStateObj.getMember -> persistentStateObj + val regionItr = persistentStateObj.getAllRegionViews.iterator() while (regionItr.hasNext) { val persistentView = regionItr.next() val regionPath = persistentView.getRegionPath - val set = regionViewSortedSet.get(regionPath) + val set = regionViewMapSortedSet.get(regionPath) if (set.isDefined) { set.get += persistentView } else { var newset = mutable.SortedSet.empty[RecoveryModePersistentView] newset += persistentView - regionViewSortedSet += regionPath -> newset + regionViewMapSortedSet += regionPath -> newset } } } assert(locatorMember != null) - // todo: handle the case when there are two locators - decide on basis of rvv in tha case mostRecentMemberObject = persistentObjectMemberMap(locatorMember) logDebug(s"The selected PersistentStateInRecoveryMode used for populating" + s" the new catalog:\n$mostRecentMemberObject") - val nonHiveRegionViews = regionViewSortedSet.filterKeys( - !_.startsWith(SystemProperties.SNAPPY_HIVE_METASTORE_PATH)) - val regionToConsider = - if (nonHiveRegionViews.isEmpty) { - logError("No relevant RecoveryModePersistentViews found.") - throw new Exception("Cannot start empty cluster in Recovery Mode.") - } else { - nonHiveRegionViews.keySet.toSeq.maxBy(nonHiveRegionViews.get(_).size) - } - val regionView = regionViewSortedSet(regionToConsider).lastKey - val memberToConsider = regionView.getMember - memberObject = persistentObjectMemberMap(memberToConsider) - logDebug(s"The selected non-Hive PersistentStateInRecoveryMode : $memberObject") val catalogObjects = mostRecentMemberObject.getCatalogObjects import scala.collection.JavaConverters._ val catalogArr = catalogObjects.asScala.map(catObj => { @@ -493,7 +509,21 @@ object RecoveryService extends Logging { } }) RecoveryService.populateCatalog(catalogArr) + + // Identify best member to get bucket-related info, etc + val nonHiveRegionViews = regionViewMapSortedSet.filterKeys( + !_.startsWith(SystemProperties.SNAPPY_HIVE_METASTORE_PATH)) + if (nonHiveRegionViews.isEmpty) { + logError("No relevant RecoveryModePersistentViews found.") + throw new Exception("Cannot start empty cluster in Recovery Mode.") + } + val memberToConsider = persistentObjectMemberMap.keySet.toSeq.sortBy(e => + persistentObjectMemberMap(e).getPrToNumBuckets.size() + + persistentObjectMemberMap(e).getReplicatedRegions.size()).last + memberObject = persistentObjectMemberMap(memberToConsider) + logDebug(s"The selected non-Hive PersistentStateInRecoveryMode : $memberObject") createSchemasMap + createCombinedSortedSet val dbList = snappyHiveExternalCatalog.listDatabases("*") val allFunctions = dbList.map(dbName => @@ -510,6 +540,79 @@ object RecoveryService extends Logging { |${allFunctions.toString()}""".stripMargin) } + def createCombinedSortedSet: Unit = { + snappyHiveExternalCatalog.getAllTables().foreach(table => { + val tableName = table.identifier.table + val schemaName = table.identifier.database.getOrElse("app") + val fqtn = (schemaName + "." + tableName).toUpperCase() + val tableType = getProvider(fqtn.toLowerCase()) + val numBuckets = getNumBuckets(schemaName.toUpperCase(), tableName.toUpperCase())._1 + var rowRegionPath: String = "" + var colRegionPath: String = "" + // TODO: check for tables with tables with _ in their name. + for (buckNum <- Range(0, numBuckets)) { + + rowRegionPath = getRowRegionPath(fqtn, buckNum) + colRegionPath = if (tableType == "column") { + PartitionedRegionHelper + .escapePRPath(getColRegionPath(schemaName, tableName, buckNum)) + .replaceFirst("___PR__B__", "/__PR/_B__") + } else "" + + val ssKey = if (colRegionPath.isEmpty) { + rowRegionPath + "#$" + } else { + rowRegionPath + "#$" + colRegionPath + } + if (regionViewMapSortedSet.contains(rowRegionPath)) { + val rowViews = regionViewMapSortedSet(rowRegionPath) + val colViews = + if (colRegionPath.nonEmpty) regionViewMapSortedSet(colRegionPath) + else mutable.SortedSet.empty[RecoveryModePersistentView] + + for (rowView <- rowViews) { + if (tableType == "column" && colViews.nonEmpty) { + for (colView <- colViews) { + if (rowView.getMember.equals(colView.getMember)) { + val set = combinedViewsMapSortedSet.get(ssKey) + if (set.isDefined) { + set.get += new RecoveryModePersistentViewPair(rowView, colView) + } else { + var newSet = mutable.SortedSet.empty[RecoveryModePersistentViewPair] + newSet += new RecoveryModePersistentViewPair(rowView, colView) + combinedViewsMapSortedSet += ssKey -> newSet + } + } + } + } else { + // case: when its a row table + val set = combinedViewsMapSortedSet.get(ssKey) + if (set.isDefined) { + set.get += new RecoveryModePersistentViewPair(rowView, null) + } else { + var newSet = mutable.SortedSet.empty[RecoveryModePersistentViewPair] + newSet += new RecoveryModePersistentViewPair(rowView, null) + combinedViewsMapSortedSet += ssKey -> newSet + } + } + } + } + } + }) + + logDebug("Printing combinedViewsMapSortedSet") + for (elem <- combinedViewsMapSortedSet) { + logDebug(s"bucket:${elem._1} :::::: Set size:${elem._2.size}\n") + for (viewPair <- elem._2) { + logDebug(s"Row View : ${viewPair.getRowView.getMember}") + if (viewPair.getColView != null) + logDebug(s"Col View : ${viewPair.getColView.getMember}") + logDebug("* ---------- *") + } + logDebug("\n\n\n") + } + } + def getTables: Seq[CatalogTable] = snappyHiveExternalCatalog.getAllTables() .filter(!_.tableType.name.equalsIgnoreCase("view")) diff --git a/store b/store index f70f4018fa..8a1dc762a2 160000 --- a/store +++ b/store @@ -1 +1 @@ -Subproject commit f70f4018fae879d4b79c563545c5c9331af54f15 +Subproject commit 8a1dc762a238d69dad0a4953fa77727093665580 From 9ab6ec16d9ded794e29f875f1a5d7ee0c3ddbdf3 Mon Sep 17 00:00:00 2001 From: hemanthmeka <36498621+hemanthmeka@users.noreply.github.com> Date: Sat, 23 Nov 2019 06:52:36 +0530 Subject: [PATCH 006/101] hs error fixes in dataextractor (#1482) * fix for hs error in data extractor * fixing random recovery test failures --- .../spark/sql/execution/oplog/impl/OpLogRdd.scala | 12 ++++-------- store | 2 +- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/core/src/main/scala/org/apache/spark/sql/execution/oplog/impl/OpLogRdd.scala b/core/src/main/scala/org/apache/spark/sql/execution/oplog/impl/OpLogRdd.scala index aeede74801..c5f469ff32 100644 --- a/core/src/main/scala/org/apache/spark/sql/execution/oplog/impl/OpLogRdd.scala +++ b/core/src/main/scala/org/apache/spark/sql/execution/oplog/impl/OpLogRdd.scala @@ -388,6 +388,7 @@ class OpLogRdd( * @param phdrCol PlaceHolderDiskRegion of column batch */ def iterateColData(phdrCol: PlaceHolderDiskRegion): Iterator[Row] = { + val directBuffers = mutable.ListBuffer.empty[ByteBuffer] if (phdrCol.getRegionMap == null || phdrCol.getRegionMap.isEmpty) return Iterator.empty val regMap = phdrCol.getRegionMap // assert(regMap != null, "region map for column batch is null") @@ -423,7 +424,8 @@ class OpLogRdd( val valueBuffer = value.getValueRetain(FetchRequest.DECOMPRESS).getBuffer val decoder = ColumnEncoding.getColumnDecoder(valueBuffer, field) val valueArray = if (valueBuffer == null || valueBuffer.isDirect) { - valueBuffer + directBuffers += valueBuffer + null } else { valueBuffer.array() } @@ -489,13 +491,7 @@ class OpLogRdd( Row.fromSeq(schema.indices.map { colIndx => val decoderAndValue = decodersAndValues(colIndx) val colDecoder = decoderAndValue._1 - var directBuffer: ByteBuffer = null - val colArray = decoderAndValue._2 match { - case b: ByteBuffer => - directBuffer = b // need reference to directBuffer till we are done reading - null - case arr: Array[Byte] => arr - } + val colArray = decoderAndValue._2 val colNextNullPosition = colDecoder.getNextNullPosition val fieldIsNull = rowNum + currentDeleted == colNextNullPosition if (fieldIsNull) { diff --git a/store b/store index 8a1dc762a2..f70f4018fa 160000 --- a/store +++ b/store @@ -1 +1 @@ -Subproject commit 8a1dc762a238d69dad0a4953fa77727093665580 +Subproject commit f70f4018fae879d4b79c563545c5c9331af54f15 From f3b4216ef80013eff87e5274b9b06b80ec3979f6 Mon Sep 17 00:00:00 2001 From: hemanthmeka <36498621+hemanthmeka@users.noreply.github.com> Date: Sat, 23 Nov 2019 07:15:15 +0530 Subject: [PATCH 007/101] converting catalog table field names to lower (#1483) --- .../snappydata/recovery/RecoveryService.scala | 3 ++- .../oplog/impl/OpLogFormatRelation.scala | 3 ++- .../sql/execution/oplog/impl/OpLogRdd.scala | 21 ++++++++++--------- 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/core/src/main/scala/io/snappydata/recovery/RecoveryService.scala b/core/src/main/scala/io/snappydata/recovery/RecoveryService.scala index 4b4f085308..62ee3f5bbb 100644 --- a/core/src/main/scala/io/snappydata/recovery/RecoveryService.scala +++ b/core/src/main/scala/io/snappydata/recovery/RecoveryService.scala @@ -360,7 +360,8 @@ object RecoveryService extends Logging { case None => throw new Exception( s"Schema name not found for the table ${table.identifier.table}") } - var schema: StructType = DataType.fromJson(schemaJsonStr).asInstanceOf[StructType] + var schema: StructType = StructType(DataType.fromJson(schemaJsonStr).asInstanceOf[StructType] + .map(f => f.copy(name = f.name.toLowerCase))) assert(schema != null, s"schemaJson read from catalog table is null " + s"for ${table.identifier.table}") diff --git a/core/src/main/scala/org/apache/spark/sql/execution/oplog/impl/OpLogFormatRelation.scala b/core/src/main/scala/org/apache/spark/sql/execution/oplog/impl/OpLogFormatRelation.scala index 3eedef4fa4..540b4bcdf2 100644 --- a/core/src/main/scala/org/apache/spark/sql/execution/oplog/impl/OpLogFormatRelation.scala +++ b/core/src/main/scala/org/apache/spark/sql/execution/oplog/impl/OpLogFormatRelation.scala @@ -58,8 +58,9 @@ class OpLogFormatRelation( val catalogTable = snappySession.externalCatalog.getTable(schemaName, tableName) val primaryKeys = catalogTable.properties.getOrElse("primary_keys", "") val keyColumns = options.getOrElse("key_columns", "") + var schemaLowerCase = StructType(schema.map(f => f.copy(name = f.name.toLowerCase))) - (new OpLogRdd(snappySession, fqtn, externalColumnTableName, schema, + (new OpLogRdd(snappySession, fqtn, externalColumnTableName, schemaLowerCase, partitioningColumns, provider, projection, filters, (filters eq null) || filters.length == 0, prunePartitions, tableSchemas, versionMap, tableColIdsMap, primaryKeys, keyColumns), projection) } diff --git a/core/src/main/scala/org/apache/spark/sql/execution/oplog/impl/OpLogRdd.scala b/core/src/main/scala/org/apache/spark/sql/execution/oplog/impl/OpLogRdd.scala index c5f469ff32..bd0d2b1056 100644 --- a/core/src/main/scala/org/apache/spark/sql/execution/oplog/impl/OpLogRdd.scala +++ b/core/src/main/scala/org/apache/spark/sql/execution/oplog/impl/OpLogRdd.scala @@ -127,11 +127,13 @@ class OpLogRdd( def getProjectColumnId(tableName: String, columnName: String): Int = { val fqtnLowerKey = tableName.replace(".", "_") - assert(versionMap.contains(fqtnLowerKey)) - val maxVersion = versionMap.getOrElse(fqtnLowerKey, null) + val maxVersion = versionMap.getOrElse(fqtnLowerKey, + throw new IllegalStateException(s"num of schema versions not found for $fqtnLowerKey")) assert(maxVersion != null) var index = -1 - val fieldsArr = tableSchemas.getOrElse(s"$maxVersion#$fqtnLowerKey", null).fields + val fieldsArr = tableSchemas.getOrElse(s"$maxVersion#$fqtnLowerKey", + throw new IllegalStateException(s"table schema not found for $maxVersion#$fqtnLowerKey")) + .fields breakable { for (i <- fieldsArr.indices) { if (fieldsArr(i).name == columnName) { @@ -142,11 +144,9 @@ class OpLogRdd( } } } - if (!tableColIdsMap.contains(s"$maxVersion#$fqtnLowerKey")) { - throw new IllegalStateException(s"tableColIdsMap might not be built properly." + - s" Missing key: $maxVersion#$fqtnLowerKey") - } - tableColIdsMap(s"$maxVersion#$fqtnLowerKey")(index) + assert(index != -1, s"column id not found for $fqtn.$columnName") + tableColIdsMap.getOrElse(s"$maxVersion#$fqtnLowerKey", + throw new IllegalStateException(s"column ids not found: $maxVersion#$fqtnLowerKey"))(index) } def getSchemaColumnId(tableName: String, colName: String, version: Int): Int = { @@ -163,8 +163,9 @@ class OpLogRdd( } } } - if (index != -1) tableColIdsMap.getOrElse(s"$version#$fqtnLowerKey", null)(index) - else -1 + assert(index != -1, s"column id not found for $fqtn.$colName") + tableColIdsMap.getOrElse(s"$version#$fqtnLowerKey", + throw new IllegalStateException(s"column ids not found: $version#$fqtnLowerKey"))(index) } /** From 421c4c232cb537bbea69304e4b0158d1a836c15a Mon Sep 17 00:00:00 2001 From: paresh-p11 <43569032+paresh-p11@users.noreply.github.com> Date: Sat, 23 Nov 2019 09:21:51 +0530 Subject: [PATCH 008/101] SNAP-3167 (#1481) * SNAP-3167 - Adding tests for the property recovery-state-chunk-size --- .../cluster/PrimaryDUnitRecoveryTest.scala | 40 ++++++++--------- .../snappydata/recovery/RecoveryService.scala | 43 +++++++++++-------- .../oplog/impl/OpLogFormatRelation.scala | 4 -- .../sql/execution/oplog/impl/OpLogRdd.scala | 16 ++++--- store | 2 +- 5 files changed, 53 insertions(+), 52 deletions(-) diff --git a/cluster/src/dunit/scala/io/snappydata/cluster/PrimaryDUnitRecoveryTest.scala b/cluster/src/dunit/scala/io/snappydata/cluster/PrimaryDUnitRecoveryTest.scala index 93148aac8b..3425b0c2ed 100644 --- a/cluster/src/dunit/scala/io/snappydata/cluster/PrimaryDUnitRecoveryTest.scala +++ b/cluster/src/dunit/scala/io/snappydata/cluster/PrimaryDUnitRecoveryTest.scala @@ -517,7 +517,6 @@ class PrimaryDUnitRecoveryTest(s: String) extends DistributedTestBase(s) // scal i = 0 } - // todo : Refactor the code. Reuse variables where possible var rs = stmtRec.executeQuery("SELECT * FROM gemfire10.test1coltab1 ORDER BY col1") logDebug("=== SELECT * FROM test1coltab1 ===\n") str.clear() @@ -748,12 +747,12 @@ class PrimaryDUnitRecoveryTest(s: String) extends DistributedTestBase(s) // scal | confdirpath: $confDirPath | ldapConf: $ldapConf""".stripMargin) - writeToFile(s"localhost -peer-discovery-port=$locatorPort -dir=$workDirPath/locator-1" + + writeToFile(s"localhost -peer-discovery-port=$locatorPort -recovery-state-chunk-size=20 -dir=$workDirPath/locator-1" + s" -client-port=$locNetPort $ldapConf", s"$confDirPath/locators") writeToFile(s"localhost -locators=localhost[$locatorPort] -dir=$workDirPath/lead-1" + s" $waitForInit $ldapConf", s"$confDirPath/leads") writeToFile( - s"""localhost -locators=localhost[$locatorPort] -dir=$workDirPath/server-1 -client-port=$netPort2 $ldapConf + s"""localhost -locators=localhost[$locatorPort] -recovery-state-chunk-size=50 -dir=$workDirPath/server-1 -client-port=$netPort2 $ldapConf |localhost -locators=localhost[$locatorPort] -dir=$workDirPath/server-2 -client-port=$netPort3 $ldapConf |""".stripMargin, s"$confDirPath/servers") @@ -861,10 +860,10 @@ class PrimaryDUnitRecoveryTest(s: String) extends DistributedTestBase(s) // scal stmt.execute("INSERT INTO gemfire10.test3tab3 select cast('asdf' as binary), cast('bnm' as clob), cast('1111111' as blob), 'adsfghi', 123456") // with option - key_columns - stmt.execute("CREATE TABLE test3coltab4 (col1 int, col2 string, col3 float) USING COLUMN" + + stmt.execute("CREATE TABLE test3_coltab4 (col1 int, col2 string, col3 float) USING COLUMN" + " OPTIONS (key_columns 'col1')") - stmt.execute("INSERT INTO test3coltab4 VALUES(1,'aaa',123.122)") - stmt.execute("INSERT INTO test3coltab4 VALUES(2,'bbb',4444.55)") + stmt.execute("INSERT INTO test3_coltab4 VALUES(1,'aaa',123.122)") + stmt.execute("INSERT INTO test3_coltab4 VALUES(2,'bbb',4444.55)") stmt.execute("CREATE TABLE test3rowtab5 (col1 FloaT NOT NULL, col2 TIMEstamp NOT NULL, col3 BOOLEAN NOT NULL," + " col4 varchar(1) NOT NULL, col5 integer NOT NULL) using row") @@ -878,9 +877,8 @@ class PrimaryDUnitRecoveryTest(s: String) extends DistributedTestBase(s) // scal stmt.execute("INSERT INTO test3coltab6 VALUES(200000000000001, 4, true)") stmt.execute("INSERT INTO test3coltab6 VALUES(300000000000001, 3, false)") - // column table - not null columns todo: add not null here - stmt.execute("CREATE TABLE test3coltab7 (col1 decimal(15,9), col2 float , col3 BIGint," + - " col4 date, col5 string ) using column options(BUCKETS '512')") + stmt.execute("CREATE TABLE test3coltab7 (col1 decimal(15,9) NOT NULL, col2 float NOT NULL, col3 BIGint NOT NULL," + + " col4 date NOT NULL, col5 string NOT NULL) using column options(BUCKETS '512')") stmt.execute("INSERT INTO test3coltab7 VALUES(891012.312321314, 1434124.123434134," + " 193471498234123, '2019-02-18', 'ZXcabcdefg')") stmt.execute("INSERT INTO test3coltab7 VALUES(91012.312321314, 34124.12343413," + @@ -888,6 +886,7 @@ class PrimaryDUnitRecoveryTest(s: String) extends DistributedTestBase(s) // scal stmt.execute("INSERT INTO test3coltab7 VALUES(1012.312321314, 4124.1234341," + " 333471498234123, '2019-03-18', 'adfcdefg')") + // todo: Paresh: the peculiar case stmt.execute("CREATE TABLE test3rowtab8 (col1 string, col2 int, col3 varchar(33)," + " col4 boolean, col5 float)using row") @@ -936,7 +935,6 @@ class PrimaryDUnitRecoveryTest(s: String) extends DistributedTestBase(s) // scal // todo: alter table -add/drop column- - stmt.close() conn.close() @@ -983,7 +981,7 @@ class PrimaryDUnitRecoveryTest(s: String) extends DistributedTestBase(s) // scal } rs = stmtRec.executeQuery("select col1, col2, col3 from" + - " gemfire10.test3coltab4 ORDER BY col1") + " gemfire10.test3_coltab4 ORDER BY col1") resetBuffer arrBuf ++= ArrayBuffer("1,aaa,123.122", "2,bbb,4444.55") while (rs.next()) { @@ -1101,7 +1099,6 @@ class PrimaryDUnitRecoveryTest(s: String) extends DistributedTestBase(s) // scal conn.close() afterEach() test_status = true - } catch { case e: Throwable => afterEach() @@ -1163,7 +1160,7 @@ class PrimaryDUnitRecoveryTest(s: String) extends DistributedTestBase(s) // scal writeToFile(s"localhost -locators=localhost[$locatorPort] -dir=$workDirPath/lead-1" + s" $waitForInit $ldapConf", s"$confDirPath/leads") writeToFile( - s"""localhost -locators=localhost[$locatorPort] -dir=$workDirPath/server-1 -client-port=$netPort2 $ldapConf + s"""localhost -locators=localhost[$locatorPort] -recovery-state-chunk-size=20 -dir=$workDirPath/server-1 -client-port=$netPort2 $ldapConf |""".stripMargin, s"$confDirPath/servers") startSnappyCluster() @@ -1219,15 +1216,14 @@ class PrimaryDUnitRecoveryTest(s: String) extends DistributedTestBase(s) // scal // row table - how nulls reflect in the recovered data files. // todo: fix this:default fails in createSchemasMap method of PrimaryDUnitRecoveryTest - stmt.execute("CREATE TABLE test5rowtab6 (col1 int, col2 string default 'DEF_VAL'," + + stmt.execute("CREATE TABLE test5_rowtab6 (col1 int, col2 string default 'DEF_VAL'," + " col3 long default -99999, col4 float default 0.0)") - // stmt.execute("CREATE TABLE test5rowtab6 (col1 int, col2 string, col3 long, col4 float)") - stmt.execute("INSERT INTO test5rowtab6 values(null, 'afadsf', 134098245, 123.123)") - stmt.execute("INSERT INTO test5rowtab6 values(null, 'afadsf', 134098245, 123.123)") - stmt.execute("INSERT INTO test5rowtab6 values(null, null, null, null)") - stmt.execute("INSERT INTO test5rowtab6 (col1,col3) values(null, 134098245 )") - stmt.execute("INSERT INTO test5rowtab6 values(null, 'afadsf', 134098245 )") - stmt.execute("INSERT INTO test5rowtab6 (col1, col4) values(null, 345345.534)") + stmt.execute("INSERT INTO test5_rowtab6 values(null, 'afadsf', 134098245, 123.123)") + stmt.execute("INSERT INTO test5_rowtab6 values(null, 'afadsf', 134098245, 123.123)") + stmt.execute("INSERT INTO test5_rowtab6 values(null, null, null, null)") + stmt.execute("INSERT INTO test5_rowtab6 (col1,col3) values(null, 134098245 )") + stmt.execute("INSERT INTO test5_rowtab6 values(null, 'afadsf', 134098245 )") + stmt.execute("INSERT INTO test5_rowtab6 (col1, col4) values(null, 345345.534)") stmt.execute("CREATE TABLE test5coltab7 (c3 Array, c4 Map < Int, Double > NOT NULL) using column") @@ -1336,7 +1332,7 @@ class PrimaryDUnitRecoveryTest(s: String) extends DistributedTestBase(s) // scal writeToFile(s"localhost -locators=localhost[$locatorPort] -dir=$workDirPath/lead-1" + s" $waitForInit $ldapConf", s"$confDirPath/leads") writeToFile( - s"localhost -locators=localhost[$locatorPort] -dir=$workDirPath/server-1 " + + s"localhost -locators=localhost[$locatorPort] -recovery-state-chunk-size=40 -dir=$workDirPath/server-1 " + s"-client-port=$netPort2 $ldapConf".stripMargin, s"$confDirPath/servers") startSnappyCluster() diff --git a/core/src/main/scala/io/snappydata/recovery/RecoveryService.scala b/core/src/main/scala/io/snappydata/recovery/RecoveryService.scala index 62ee3f5bbb..f5f34a38e4 100644 --- a/core/src/main/scala/io/snappydata/recovery/RecoveryService.scala +++ b/core/src/main/scala/io/snappydata/recovery/RecoveryService.scala @@ -20,15 +20,18 @@ package io.snappydata.recovery import java.util.function.BiConsumer -import com.pivotal.gemfirexd.internal.engine.ui.{SnappyExternalTableStats, SnappyIndexStats, SnappyRegionStats} +import com.pivotal.gemfirexd.internal.engine.ui.{SnappyExternalTableStats, SnappyIndexStats, + SnappyRegionStats} import com.gemstone.gemfire.distributed.internal.membership.InternalDistributedMember import com.gemstone.gemfire.internal.cache.PartitionedRegionHelper import com.gemstone.gemfire.internal.shared.SystemProperties import com.pivotal.gemfirexd.Attribute -import com.pivotal.gemfirexd.internal.engine.ddl.{DDLConflatable, GfxdDDLQueueEntry, GfxdDDLRegionQueue} +import com.pivotal.gemfirexd.internal.engine.ddl.{DDLConflatable, GfxdDDLQueueEntry, + GfxdDDLRegionQueue} import com.pivotal.gemfirexd.internal.engine.distributed.RecoveryModeResultCollector import com.pivotal.gemfirexd.internal.engine.distributed.message.PersistentStateInRecoveryMode -import com.pivotal.gemfirexd.internal.engine.distributed.message.PersistentStateInRecoveryMode.{RecoveryModePersistentView, RecoveryModePersistentViewPair} +import com.pivotal.gemfirexd.internal.engine.distributed.message.PersistentStateInRecoveryMode +.{RecoveryModePersistentView, RecoveryModePersistentViewPair} import com.pivotal.gemfirexd.internal.engine.sql.execute.RecoveredMetadataRequestMessage import scala.collection.JavaConverters.asScalaBufferConverter import scala.collection.mutable @@ -42,12 +45,13 @@ import io.snappydata.Constant import org.apache.spark.sql.{SnappyContext, SnappyParser, SnappySession} import io.snappydata.sql.catalog.ConnectorExternalCatalog -import io.snappydata.thrift.{CatalogFunctionObject, CatalogMetadataDetails, CatalogSchemaObject, CatalogTableObject} +import io.snappydata.thrift.{CatalogFunctionObject, CatalogMetadataDetails, CatalogSchemaObject, + CatalogTableObject} import org.apache.spark.sql.catalyst.catalog.{CatalogDatabase, CatalogFunction, CatalogTable} import org.apache.spark.sql.types.{DataType, MetadataBuilder, StructField, StructType} -import org.apache.spark.{Logging, SparkContext} -import org.apache.spark.sql.hive.{HiveClientUtil, SnappyHiveExternalCatalog} +import org.apache.spark.Logging +import org.apache.spark.sql.hive.HiveClientUtil import org.apache.spark.sql.internal.ContextJarUtils object RecoveryService extends Logging { @@ -159,7 +163,8 @@ object RecoveryService extends Logging { val dbList = snappyHiveExternalCatalog.listDatabases("*").filter(dbName => !(dbName.equalsIgnoreCase("SYS") || dbName.equalsIgnoreCase("DEFAULT"))) - val allFunctions = dbList.flatMap(dbName => snappyHiveExternalCatalog.listFunctions(dbName, "*") + val allFunctions = dbList.flatMap(dbName => snappyHiveExternalCatalog + .listFunctions(dbName, "*") .map(func => snappyHiveExternalCatalog.getFunction(dbName, func))) val allDatabases = dbList.map(snappyHiveExternalCatalog.getDatabase) allFunctions.foreach(func => { @@ -212,7 +217,8 @@ object RecoveryService extends Logging { }) // the sorting is required to arrange statements amongst tables - val sortedTempTableBuffer = tempTableBuffer.sortBy(tup => tup._1.split("_")(1).toLong).map(_._2) + val sortedTempTableBuffer = + tempTableBuffer.sortBy(tup => tup._1.split("_")(1).toLong).map(_._2) ddlBuffer.appendAll(sortedTempTableBuffer) // view ddls should be at the end so that the extracted ddls won't fail when replayed as is. @@ -222,13 +228,13 @@ object RecoveryService extends Logging { def accept(alias: String, cmd: String): Unit = { if (!(alias.equals(Constant.CLUSTER_ID) || alias.startsWith(Constant.MEMBER_ID_PREFIX))) { - logInfo("#RecoveryService " + alias + cmd) val cmdFields = cmd.split("\\|", -1) if (cmdFields.length > 1) { val repos = cmdFields(1) val path = cmdFields(2) if (!repos.isEmpty && !path.isEmpty) { - ddlBuffer.append(s"DEPLOY PACKAGE $alias '${cmdFields(0)}' repos '$repos' path '$path'") + ddlBuffer + .append(s"DEPLOY PACKAGE $alias '${cmdFields(0)}' repos '$repos' path '$path'") } else if (!repos.isEmpty && path.isEmpty) { ddlBuffer.append(s"DEPLOY PACKAGE $alias '${cmdFields(0)}' repos '$repos'") @@ -282,10 +288,11 @@ object RecoveryService extends Logging { def getExecutorHost(fqtn: String, bucketId: Int = -1): Seq[String] = { val rowRegionPath = getRowRegionPath(fqtn, bucketId) // for null region maps select random host - val rowRegionPathKey = combinedViewsMapSortedSet.keySet.filter(_.contains(rowRegionPath + "#$")) + val rowRegionPathKey = combinedViewsMapSortedSet.keySet.filter(_.contains(rowRegionPath+"#$")) if (rowRegionPathKey.size != 0) { - assert(rowRegionPathKey.size == 1, s"combinedViewsMapSortedSet should not contain multiple entries for the key $rowRegionPath") + assert(rowRegionPathKey.size == 1, + s"combinedViewsMapSortedSet should not contain multiple entries for the key $rowRegionPath") val viewPair = combinedViewsMapSortedSet(rowRegionPathKey.head).lastKey val hostCanonical = viewPair.getRowView.getExecutorHost val host = hostCanonical.split('(').head @@ -300,8 +307,8 @@ object RecoveryService extends Logging { } def getRandomExecutorHost: Seq[String] = { - val e = Random.shuffle(regionViewMapSortedSet.toList).head._2.firstKey - val hostCanonical = e.getExecutorHost + val randomPersistentView = Random.shuffle(regionViewMapSortedSet.toList).head._2.firstKey + val hostCanonical = randomPersistentView.getExecutorHost val host = hostCanonical.split('(').head Seq(s"executor_${host}_$hostCanonical") } @@ -375,7 +382,7 @@ object RecoveryService extends Logging { versionMap.put(fqtnKey, versionCnt) versionCnt += 1 - // Alter statements contains original sql with timestamp in keys to find sequence. for example + // Alter statements contains original sql with timestamp in keys to find sequence.for example // Properties: [k1=v1, altTxt_1568129777251=, k3=v3] val altStmtKeysSorted = table.properties.keys .filter(_.contains(s"altTxt_")).toSeq @@ -458,7 +465,8 @@ object RecoveryService extends Logging { val msg = new RecoveredMetadataRequestMessage(collector) msg.executeFunction() val persistentData = collector.getResult - logDebug(s" Total Number of PersistentStateInRecoveryMode objects received ${persistentData.size()}") + logDebug(s"Total Number of PersistentStateInRecoveryMode objects received" + + s" ${persistentData.size()}") val itr = persistentData.iterator() while (itr.hasNext) { val persistentStateObj = itr.next().asInstanceOf[PersistentStateInRecoveryMode] @@ -490,8 +498,6 @@ object RecoveryService extends Logging { } assert(locatorMember != null) mostRecentMemberObject = persistentObjectMemberMap(locatorMember) - - logDebug(s"The selected PersistentStateInRecoveryMode used for populating" + s" the new catalog:\n$mostRecentMemberObject") @@ -550,7 +556,6 @@ object RecoveryService extends Logging { val numBuckets = getNumBuckets(schemaName.toUpperCase(), tableName.toUpperCase())._1 var rowRegionPath: String = "" var colRegionPath: String = "" - // TODO: check for tables with tables with _ in their name. for (buckNum <- Range(0, numBuckets)) { rowRegionPath = getRowRegionPath(fqtn, buckNum) diff --git a/core/src/main/scala/org/apache/spark/sql/execution/oplog/impl/OpLogFormatRelation.scala b/core/src/main/scala/org/apache/spark/sql/execution/oplog/impl/OpLogFormatRelation.scala index 540b4bcdf2..b8e8c9faed 100644 --- a/core/src/main/scala/org/apache/spark/sql/execution/oplog/impl/OpLogFormatRelation.scala +++ b/core/src/main/scala/org/apache/spark/sql/execution/oplog/impl/OpLogFormatRelation.scala @@ -16,8 +16,6 @@ */ package org.apache.spark.sql.execution.oplog.impl -import java.util - import io.snappydata.Constant import io.snappydata.recovery.RecoveryService @@ -46,8 +44,6 @@ class OpLogFormatRelation( def scnTbl(externalColumnTableName: String, requiredColumns: Array[String], filters: Array[Expression], prunePartitions: () => Int): (RDD[Any], Array[Int]) = { - val fieldNames = new util.HashMap[String, Integer](schema.length) - (0 until schema.length).foreach(i => fieldNames.put(schema(i).name.toLowerCase, i + 1)) val projection = null val provider = RecoveryService.getProvider(fqtn) val snappySession = SparkSession.builder().getOrCreate().asInstanceOf[SnappySession] diff --git a/core/src/main/scala/org/apache/spark/sql/execution/oplog/impl/OpLogRdd.scala b/core/src/main/scala/org/apache/spark/sql/execution/oplog/impl/OpLogRdd.scala index bd0d2b1056..ded8e60be2 100644 --- a/core/src/main/scala/org/apache/spark/sql/execution/oplog/impl/OpLogRdd.scala +++ b/core/src/main/scala/org/apache/spark/sql/execution/oplog/impl/OpLogRdd.scala @@ -44,8 +44,10 @@ import org.apache.spark.serializer.StructTypeSerializer import org.apache.spark.sql.catalyst.expressions.Expression import org.apache.spark.sql.catalyst.util.{DateTimeUtils, SerializedArray, SerializedMap, SerializedRow} import org.apache.spark.sql.execution.RDDKryo -import org.apache.spark.sql.execution.columnar.encoding.{ColumnDecoder, ColumnDeleteDecoder, ColumnDeltaDecoder, ColumnEncoding, ColumnStatsSchema, UpdatedColumnDecoder} -import org.apache.spark.sql.execution.columnar.impl.{ColumnDelta, ColumnFormatEntry, ColumnFormatKey, ColumnFormatValue} +import org.apache.spark.sql.execution.columnar.encoding.{ColumnDecoder, ColumnDeleteDecoder, + ColumnDeltaDecoder, ColumnEncoding, ColumnStatsSchema, UpdatedColumnDecoder} +import org.apache.spark.sql.execution.columnar.impl.{ColumnDelta, ColumnFormatEntry, + ColumnFormatKey, ColumnFormatValue} import org.apache.spark.sql.types._ import org.apache.spark.sql.{Row, SnappySession} import org.apache.spark.unsafe.Platform @@ -87,8 +89,8 @@ class OpLogRdd( val dataTypeDescriptor = dataType match { case LongType => DataTypeDescriptor.getBuiltInDataTypeDescriptor(Types.BIGINT, isNullable) - case IntegerType => DataTypeDescriptor.getBuiltInDataTypeDescriptor(Types.INTEGER, isNullable) - case BooleanType => DataTypeDescriptor.getBuiltInDataTypeDescriptor(Types.BOOLEAN, isNullable) + case IntegerType => DataTypeDescriptor.getBuiltInDataTypeDescriptor(Types.INTEGER,isNullable) + case BooleanType => DataTypeDescriptor.getBuiltInDataTypeDescriptor(Types.BOOLEAN,isNullable) case ByteType => DataTypeDescriptor.getBuiltInDataTypeDescriptor(Types.SMALLINT, isNullable) case FloatType => DataTypeDescriptor.getSQLDataTypeDescriptor("float", isNullable) case BinaryType => DataTypeDescriptor.getBuiltInDataTypeDescriptor(Types.BLOB, isNullable) @@ -129,7 +131,7 @@ class OpLogRdd( val fqtnLowerKey = tableName.replace(".", "_") val maxVersion = versionMap.getOrElse(fqtnLowerKey, throw new IllegalStateException(s"num of schema versions not found for $fqtnLowerKey")) - assert(maxVersion != null) + assert(maxVersion != 0) var index = -1 val fieldsArr = tableSchemas.getOrElse(s"$maxVersion#$fqtnLowerKey", throw new IllegalStateException(s"table schema not found for $maxVersion#$fqtnLowerKey")) @@ -247,8 +249,10 @@ class OpLogRdd( data } else null case BinaryType => + if (!dvd.isNull){ val blobValue = dvd.getObject.asInstanceOf[HarmonySerialBlob] Source.fromInputStream(blobValue.getBinaryStream).map(e => e.toByte).toArray + } else null case _ => dvd.getObject } } @@ -740,4 +744,4 @@ class OpLogRdd( } schema = StructTypeSerializer.read(kryo, input, c = null) } -} \ No newline at end of file +} diff --git a/store b/store index f70f4018fa..74a839b1e3 160000 --- a/store +++ b/store @@ -1 +1 @@ -Subproject commit f70f4018fae879d4b79c563545c5c9331af54f15 +Subproject commit 74a839b1e331077767101799947b703ebba54f3c From ae7f90592495037fa07bd5cd56f37c0ec5e2ea13 Mon Sep 17 00:00:00 2001 From: ahshahid Date: Fri, 22 Nov 2019 21:32:23 -0800 Subject: [PATCH 009/101] linking --- store | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/store b/store index f70f4018fa..fc72d44900 160000 --- a/store +++ b/store @@ -1 +1 @@ -Subproject commit f70f4018fae879d4b79c563545c5c9331af54f15 +Subproject commit fc72d44900ce68e25c0dd1bd9a63e5339cbc1f06 From 533b6a62c58ac45da528a902674471b3d309378b Mon Sep 17 00:00:00 2001 From: kneeraj Date: Sat, 23 Nov 2019 15:47:52 +0530 Subject: [PATCH 010/101] New interpreter support through new script snappy-shell (#1465) * Added support for SQL command for Scala code execution. Anything starting with 'scala exec' is executed on the lead node. * Added a cli snappy-scala for direct scala code execution. Built over IJ. * Added support for scala, spark-shell type colonCommands. Overridden some commands to suit SnappyData like replay, reset, quit, etc. * Support for grant revoke for scala interpreter privilege. Only db owner can grant or revoke this privilege. By default only db owner has this privilege. * Metacommandregion can keep object also now and not only strings. So changes to avoid blind casting to Strings wherever applicable. * Fix for ConsoleReader trying to expand input on '!' char in interpreter mode. Basically diabled '!' it using a system property mechanism provided by ConsoleReader. --- cluster/bin/snappy-scala | 26 ++ .../io/snappydata/ToolsCallbackImpl.scala | 17 +- .../gemxd/ClusterCallbacksImpl.scala | 8 +- .../gemxd/SparkSQLExecuteImpl.scala | 4 +- .../metrics/SnappyMetricsSystem.scala | 16 +- .../RemoteInterpreterStateHolder.scala | 292 ++++++++++++++++++ .../SnappyInterpreterExecute.scala | 210 +++++++++++++ .../snappydata/tools/SnappyUtilLauncher.scala | 125 +++++++- .../scala/io/snappydata/ToolsCallback.scala | 4 +- .../snappydata/recovery/RecoveryService.scala | 9 +- .../apache/spark/sql/SnappyBaseParser.scala | 3 + .../org/apache/spark/sql/SnappyContext.scala | 49 +-- .../apache/spark/sql/SnappyDDLParser.scala | 47 ++- .../org/apache/spark/sql/execution/ddl.scala | 129 +++++--- .../apache/spark/sql/internal/JarUtils.scala | 21 +- .../main/scala/io/snappydata/Constant.scala | 2 + 16 files changed, 862 insertions(+), 100 deletions(-) create mode 100755 cluster/bin/snappy-scala create mode 100644 cluster/src/main/scala/io/snappydata/remote/interpreter/RemoteInterpreterStateHolder.scala create mode 100644 cluster/src/main/scala/io/snappydata/remote/interpreter/SnappyInterpreterExecute.scala diff --git a/cluster/bin/snappy-scala b/cluster/bin/snappy-scala new file mode 100755 index 0000000000..7a7b5fbc2f --- /dev/null +++ b/cluster/bin/snappy-scala @@ -0,0 +1,26 @@ +#!/usr/bin/env bash + +# +# Copyright (c) 2017-2019 TIBCO Software Inc. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you +# may not use this file except in compliance with the License. You +# may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. See the License for the specific language governing +# permissions and limitations under the License. See accompanying +# LICENSE file. +# + +function absPath() { + perl -MCwd -le 'print Cwd::abs_path(shift)' "$1" +} +bin="$(dirname "$(absPath "$0")")" + +export SNAPPY_SCRIPT_NAME=snappy-scala +exec "$bin/snappy" "$@" diff --git a/cluster/src/main/scala/io/snappydata/ToolsCallbackImpl.scala b/cluster/src/main/scala/io/snappydata/ToolsCallbackImpl.scala index ae0957769d..d2c96ccf6e 100644 --- a/cluster/src/main/scala/io/snappydata/ToolsCallbackImpl.scala +++ b/cluster/src/main/scala/io/snappydata/ToolsCallbackImpl.scala @@ -21,7 +21,6 @@ import java.lang.reflect.InvocationTargetException import java.net.{URI, URLClassLoader} import scala.collection.JavaConverters._ - import com.gemstone.gemfire.cache.EntryExistsException import com.pivotal.gemfirexd.internal.engine.Misc import com.pivotal.gemfirexd.internal.engine.distributed.utils.GemFireXDUtils @@ -29,7 +28,7 @@ import com.pivotal.gemfirexd.internal.iapi.error.StandardException import com.pivotal.gemfirexd.internal.shared.common.reference.SQLState import io.snappydata.cluster.ExecutorInitiator import io.snappydata.impl.{ExtendibleURLClassLoader, LeadImpl} - +import io.snappydata.remote.interpreter.SnappyInterpreterExecute import org.apache.spark.executor.SnappyExecutor import org.apache.spark.sql.SnappyContext import org.apache.spark.sql.execution.columnar.ExternalStoreUtils @@ -41,6 +40,8 @@ import org.apache.spark.ui.{JettyUtils, SnappyDashboardTab} import org.apache.spark.util.SnappyUtils import org.apache.spark.{Logging, SparkCallbacks, SparkContext, SparkFiles} +import scala.collection.immutable.HashSet + object ToolsCallbackImpl extends ToolsCallback with Logging { override def updateUI(sc: SparkContext): Unit = { @@ -140,7 +141,8 @@ object ToolsCallbackImpl extends ToolsCallback with Logging { if (!args(0).isEmpty) { // args(0) = appname-filename val appName = args(0).split('-')(0) // This url points to the jar on the file server - val url = Misc.getMemStore.getMetadataCmdRgn.get(ContextJarUtils.functionKeyPrefix + appName) + val urlObj = Misc.getMemStore.getMetadataCmdRgn.get(ContextJarUtils.functionKeyPrefix + appName) + val url: String = if (urlObj != null) urlObj.toString else null if (url != null && !url.isEmpty) { val executor = ExecutorInitiator.snappyExecBackend.executor.asInstanceOf[SnappyExecutor] val cachedFileName = s"${url.hashCode}-1_cache" @@ -190,10 +192,11 @@ object ToolsCallbackImpl extends ToolsCallback with Logging { !(p.startsWith(ContextJarUtils.functionKeyPrefix) || p.equals(Constant.CLUSTER_ID) || p.startsWith(Constant.MEMBER_ID_PREFIX))) - r.getAll(keys.asJava).values().toArray.map(_.asInstanceOf[String]) + r.getAll(keys.asJava).values().toArray.filter( + _.isInstanceOf[String]).map(_.asInstanceOf[String]) } - override def getGlobalCmndsSet: java.util.Set[java.util.Map.Entry[String, String]] = { + override def getGlobalCmndsSet: java.util.Set[java.util.Map.Entry[String, Object]] = { GemFireXDUtils.waitForNodeInitialization() Misc.getMemStore.getMetadataCmdRgn.entrySet() } @@ -248,4 +251,8 @@ object ToolsCallbackImpl extends ToolsCallback with Logging { updatedURLs.foreach(url => lead.urlclassloader.addURL(url)) Thread.currentThread().setContextClassLoader(lead.urlclassloader) } + + override def updateIntpGrantRevoke(grantor: String, isGrant: Boolean, users: String): Unit = { + SnappyInterpreterExecute.handleNewPermissions(grantor, isGrant, users) + } } diff --git a/cluster/src/main/scala/io/snappydata/gemxd/ClusterCallbacksImpl.scala b/cluster/src/main/scala/io/snappydata/gemxd/ClusterCallbacksImpl.scala index e862adc617..62192b42c6 100644 --- a/cluster/src/main/scala/io/snappydata/gemxd/ClusterCallbacksImpl.scala +++ b/cluster/src/main/scala/io/snappydata/gemxd/ClusterCallbacksImpl.scala @@ -25,7 +25,6 @@ import scala.util.Try import scala.collection.mutable.ArrayBuffer import scala.util.Try - import com.gemstone.gemfire.distributed.internal.membership.InternalDistributedMember import com.gemstone.gemfire.internal.cache.GemFireCacheImpl import com.gemstone.gemfire.internal.shared.Version @@ -35,12 +34,12 @@ import com.pivotal.gemfirexd.internal.engine.Misc import com.pivotal.gemfirexd.internal.iapi.sql.ParameterValueSet import com.pivotal.gemfirexd.internal.iapi.types.DataValueDescriptor import com.pivotal.gemfirexd.internal.impl.sql.execute.ValueRow -import com.pivotal.gemfirexd.internal.snappy.{CallbackFactoryProvider, ClusterCallbacks, LeadNodeExecutionContext, SparkSQLExecute} +import com.pivotal.gemfirexd.internal.snappy._ import io.snappydata.cluster.ExecutorInitiator import io.snappydata.impl.LeadImpl import io.snappydata.recovery.RecoveryService +import io.snappydata.remote.interpreter.SnappyInterpreterExecute import io.snappydata.{ServiceManager, SnappyEmbeddedTableStatsProviderService} - import org.apache.spark.Logging import org.apache.spark.scheduler.cluster.SnappyClusterManager import org.apache.spark.serializer.{KryoSerializerPool, StructTypeSerializer} @@ -259,4 +258,7 @@ object ClusterCallbacksImpl extends ClusterCallbacks with Logging { case _ => } } + + override def getInterpreterExecution(sql: String, v: Version, + connId: lang.Long): InterpreterExecute = new SnappyInterpreterExecute(sql, connId) } diff --git a/cluster/src/main/scala/io/snappydata/gemxd/SparkSQLExecuteImpl.scala b/cluster/src/main/scala/io/snappydata/gemxd/SparkSQLExecuteImpl.scala index 2d7197ae58..acc27ad02d 100644 --- a/cluster/src/main/scala/io/snappydata/gemxd/SparkSQLExecuteImpl.scala +++ b/cluster/src/main/scala/io/snappydata/gemxd/SparkSQLExecuteImpl.scala @@ -21,7 +21,6 @@ import java.sql.SQLWarning import scala.collection.JavaConverters._ import scala.collection.mutable.ArrayBuffer - import com.gemstone.gemfire.DataSerializer import com.gemstone.gemfire.cache.CacheClosedException import com.gemstone.gemfire.internal.shared.{ClientSharedUtils, Version} @@ -38,8 +37,8 @@ import com.pivotal.gemfirexd.internal.iapi.types.{DataValueDescriptor, SQLChar} import com.pivotal.gemfirexd.internal.impl.sql.execute.ValueRow import com.pivotal.gemfirexd.internal.shared.common.StoredFormatIds import com.pivotal.gemfirexd.internal.snappy.{LeadNodeExecutionContext, SparkSQLExecute} +import io.snappydata.remote.interpreter.SnappyInterpreterExecute import io.snappydata.{Constant, Property, QueryHint} - import org.apache.spark.serializer.{KryoSerializerPool, StructTypeSerializer} import org.apache.spark.sql.catalyst.expressions import org.apache.spark.sql.catalyst.util.DateTimeUtils @@ -498,6 +497,7 @@ object SnappySessionPerConnection { def removeSnappySession(connectionID: java.lang.Long): Unit = { val session = connectionIdMap.remove(connectionID) if (session ne null) session.clear() + SnappyInterpreterExecute.closeRemoteInterpreter(connectionID) } } diff --git a/cluster/src/main/scala/io/snappydata/metrics/SnappyMetricsSystem.scala b/cluster/src/main/scala/io/snappydata/metrics/SnappyMetricsSystem.scala index 735e2aa688..8ee3f1991d 100644 --- a/cluster/src/main/scala/io/snappydata/metrics/SnappyMetricsSystem.scala +++ b/cluster/src/main/scala/io/snappydata/metrics/SnappyMetricsSystem.scala @@ -40,15 +40,27 @@ object SnappyMetricsSystem { GemFireXDUtils.waitForNodeInitialization() // initialize metric system with cluster id as metrics namespace - val clusterUuid = Misc.getMemStore.getMetadataCmdRgn.get(Constant.CLUSTER_ID) + val clusterUuidObj = Misc.getMemStore.getMetadataCmdRgn.get(Constant.CLUSTER_ID) + val clusterUuid: String = if (clusterUuidObj != null) { + clusterUuidObj.asInstanceOf[String] + } else null UserMetricsSystem.initialize(sc, clusterUuid) // store every member diskStore ID to metadataCmdRgn putMembersDiskStoreIdInRegion() - val allMetaEntries = Misc.getMemStore.getMetadataCmdRgn. + val allMetaEntriesObj = Misc.getMemStore.getMetadataCmdRgn. getAll(Misc.getMemStore.getMetadataCmdRgn.keySet()) + val allMetaEntries: util.Map[String, String] = new util.HashMap() + val itr = allMetaEntriesObj.entrySet().iterator() + while (itr.hasNext) { + val entry = itr.next() + if (entry.getValue.isInstanceOf[String]) { + val valStr = entry.getValue.asInstanceOf[String] + allMetaEntries.put(entry.getKey, valStr) + } + } val timeInterval = 5000 // concurrently executing threads to get stats from StatsProviderServices diff --git a/cluster/src/main/scala/io/snappydata/remote/interpreter/RemoteInterpreterStateHolder.scala b/cluster/src/main/scala/io/snappydata/remote/interpreter/RemoteInterpreterStateHolder.scala new file mode 100644 index 0000000000..803ac8d3e5 --- /dev/null +++ b/cluster/src/main/scala/io/snappydata/remote/interpreter/RemoteInterpreterStateHolder.scala @@ -0,0 +1,292 @@ +/* + * Copyright (c) 2017-2019 TIBCO Software Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you + * may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. See accompanying + * LICENSE file. + */ + +package io.snappydata.remote.interpreter + +import java.io._ +import java.lang.reflect.Method +import java.net.URLClassLoader + +import com.gemstone.gemfire.internal.shared.StringPrintWriter +import com.pivotal.gemfirexd.Attribute +import com.pivotal.gemfirexd.internal.engine.Misc +import io.snappydata.gemxd.SnappySessionPerConnection +import org.apache.spark.SparkContext +import org.apache.spark.repl.SparkILoop +import org.apache.spark.sql.SnappySession + +import scala.collection.mutable +import scala.tools.nsc.Settings +import scala.tools.nsc.interpreter.{IMain, LoopCommands, Results} + +class RemoteInterpreterStateHolder(val connId: Long, val user: String, val authToken: String) { + + val sc: SparkContext = SparkContext.getOrCreate() + val snappy = SnappySessionPerConnection.getSnappySessionForConnection(connId) + + snappy.conf.set(Attribute.USERNAME_ATTR, user) + snappy.conf.set(Attribute.PASSWORD_ATTR, authToken) + + lazy val pw = new StringPrintWriter() + lazy val strOpStream = new StringOutputStrem(pw) + + var intp: SparkILoop = createSparkILoop + initIntp() + + val allInterpretedLinesForReplay: mutable.ArrayBuffer[String] = new mutable.ArrayBuffer[String]() + + private def initIntp(): Unit = { + intp.interpret("import org.apache.spark.sql.functions._") + intp.interpret("org.apache.spark.sql.SnappySession") + intp.bind("sc", sc) + intp.bind("snappy", snappy) + pw.reset() + } + + + lazy val commandMethod: Method = { + val methods = this.intp.getClass.getSuperclass.getSuperclass.getDeclaredMethods + val commandmethod = methods.find(_.getName == "colonCommand").getOrElse( + throw new IllegalStateException("expected colonCommand to be there")) + commandmethod.setAccessible(true) + commandmethod + } + + var incomplete = new mutable.StringBuilder() + val resultBuffer = new mutable.ArrayBuffer[String]() + + def interpret(code: Array[String]): Array[String] = { + return interpret(code, false) + } + + def interpret(code: Array[String], replay: Boolean): Array[String] = { + this.resultBuffer.clear() + pw.reset() + if (code != null && !code.isEmpty && code(0).trim.startsWith(":")) { + return processCommand(code(0).tail) + } + scala.Console.setOut(strOpStream) + val tmpsb = new StringBuilder + tmpsb.append(incomplete.toString()) + incomplete.setLength(0) + var i = 0 + var lastResult: Results.Result = Results.Success + while(i < code.length && !(lastResult == Results.Error)) { + val line = code(i) + if (tmpsb.isEmpty) tmpsb.append(line) + else tmpsb.append("\n" + line) + if (replay) println(line) + lastResult = intp.interpret(tmpsb.toString()) + if (!(lastResult == Results.Error) && !replay) { + allInterpretedLinesForReplay += line + } + if (lastResult == Results.Success) tmpsb.clear() + resultBuffer += pw.toString.stripLineEnd + pw.reset() + i += 1 + } + // return empty. process command will do the needful + if (replay) return Array.empty + + if (!(lastResult == Results.Incomplete)) { + pw.reset() + incomplete.setLength(0) + } else { + incomplete.append(tmpsb.toString()) + resultBuffer += "___INCOMPLETE___" + } + resultBuffer.toArray + } + + def processCommand(command: String): Array[String] = { + scala.Console.setOut(strOpStream) + val result = commandMethod.invoke(this.intp, command) + if (resultBuffer.isEmpty) { + val output = pw.toString + val returnArray = output.split("\n") + // For help we need a little change in the default display. + if (!command.isEmpty && "help".contains(command)) { + returnArray.map { + case x if x.contains("All commands can be abbreviated") => modifiedHelpHeaderLine(x) + case x => x + } + } else { + returnArray + } + } else { + // For help we need a little change in the default display. + resultBuffer.toArray + } + } + + private lazy val modifiedHelpHeaderLine = (s: String) => { + val modifiedOrigLine = s.replace("All commands", "Most of the commands") + val nonModifiableStmnt = s"\nSome Commands that cannot be abbreviated are: 'run', 'elapsedtime on',\n " + + s"'maximumdisplaywidth' and 'maximumlinewidth'\n" + modifiedOrigLine + nonModifiableStmnt + } + + def createSparkILoop: SparkILoop = { + val settings: Settings = new Settings + var classpath: String = "" + val paths: Seq[File] = currentClassPath() + for (f <- paths) { + if (classpath.length > 0) classpath += File.pathSeparator + classpath += f.getAbsolutePath + } + val in = new BufferedReader(new StringReader("")) + val intp = new RemoteILoop(pw, this) + settings.classpath.value = classpath + intp.settings = settings + intp.createInterpreter() + pw.reset() + intp + } + + def close(): Unit = { + intp.clearExecutionWrapper() + intp.close() + strOpStream.close() + pw.close() + snappy.clear() + incomplete.setLength(0) + allInterpretedLinesForReplay.clear() + } + + private def currentClassPath(): Seq[File] = { + val paths = classPath(Thread.currentThread.getContextClassLoader) + val cps = System.getProperty("java.class.path").split(File.pathSeparator) + if (cps != null) { + for (cp <- cps) { + paths += new File(cp) + } + } + paths + } + + private def classPath(cl: ClassLoader): mutable.MutableList[File] = { + val paths = new mutable.MutableList[File] + if (cl == null) return paths + cl match { + case ucl: URLClassLoader => + val urls = ucl.getURLs + if (urls != null) for (url <- urls) { + paths += new File(url.getFile) + } + case _ => + } + paths + } + + def replayCmd(): Unit = { + if (allInterpretedLinesForReplay.nonEmpty) { + val copy = allInterpretedLinesForReplay.clone() + resetCmd() + interpret(copy.toArray, true) + } else { + println("Nothing to replay") + } + } + + def resetCmd(): Unit = { + intp.clearExecutionWrapper() + intp.close() + pw.reset() + intp = createSparkILoop + initIntp() + incomplete.setLength(0) + allInterpretedLinesForReplay.clear() + } + + def history(): Unit = { + allInterpretedLinesForReplay.foreach(println(_)) + } + + // The below commands are executed locally in ij + // Kept here just so that :help prints them too. But that is why + // it will throw exception as these should never come here + def maxdisplaywidth(arg: String): Unit = { + throw new IllegalArgumentException("maxdisplaywidth not expected to run on lead"); + } + + def maxlinewidth(arg: String): Unit = { + throw new IllegalArgumentException("maxlinewidth not expected to run on lead"); + } + + def run(arg: String): Unit = { + throw new IllegalArgumentException("run not expected to run on lead"); + } + + def elapsedtime(): Unit = { + throw new IllegalArgumentException("elapsedtime not expected to run on lead"); + } + + def quit(): Unit = { + throw new IllegalArgumentException("quit not expected to run on lead"); + } + + class StringOutputStrem(val spw: StringPrintWriter) extends OutputStream { + override def write(b: Int): Unit = { + spw.write(b) + } + } +} + +class RemoteILoop(spw: StringPrintWriter, intpHelper: RemoteInterpreterStateHolder) + extends SparkILoop(null.asInstanceOf[BufferedReader], new PrintWriter(spw)) { + + /** Available commands */ + override def commands: List[LoopCommand] = serviceableCommands + + lazy val serviceableCommands: List[RemoteILoop.this.LoopCommand] = { + val inheritedCommands = sparkStandardCommands.filterNot( + cmd => RemoteILoop.notTBeInheritedCommandNames.contains(cmd.name)) + val implementedCommands = RemoteILoop.snappyOverrideImpls.map { + case "replay" => LoopCommand.nullary( + "replay", "rerun all the commands since the start", intpHelper.replayCmd) + case "reset" => LoopCommand.nullary( + "reset", "reset the interpreter state", intpHelper.resetCmd) + case "history" => LoopCommand.nullary( + "history", "shows the history of commands", intpHelper.history) + case x => throw new IllegalArgumentException(s"did not expect command $x") + } + + // The below commands are executed locally in ij + // Kept here just so that :help prints them too. + val localIJCommands = List( + LoopCommand.cmd("run", "", + "runs the scala file in order", intpHelper.run), + LoopCommand.nullary( + "elapsedtime on", "shows time taken to interpret the code", intpHelper.elapsedtime), + LoopCommand.nullary( + "quit", "cleanup and close interpreter", intpHelper.quit), + LoopCommand.cmd("maximumdisplaywidth", "", + "a number specifying width of display", intpHelper.maxdisplaywidth), + LoopCommand.cmd("maximumlinewidth", "", + "a number specifying width of line", intpHelper.maxlinewidth) + ) + inheritedCommands ++ implementedCommands ++ localIJCommands + } +} + +object RemoteILoop { + private val notTBeInheritedCommandNames = Set( + "h?", "edit", "line", "load", "paste", "power", + "quit", "replay", "reset", "settings", "history") + + private val snappyOverrideImpls = Set("replay", "reset", "history") +} \ No newline at end of file diff --git a/cluster/src/main/scala/io/snappydata/remote/interpreter/SnappyInterpreterExecute.scala b/cluster/src/main/scala/io/snappydata/remote/interpreter/SnappyInterpreterExecute.scala new file mode 100644 index 0000000000..4c9e82e079 --- /dev/null +++ b/cluster/src/main/scala/io/snappydata/remote/interpreter/SnappyInterpreterExecute.scala @@ -0,0 +1,210 @@ +/* + * Copyright (c) 2017-2019 TIBCO Software Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you + * may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. See accompanying + * LICENSE file. + */ + + +package io.snappydata.remote.interpreter + +import java.io.Serializable +import java.util.concurrent.locks.ReentrantReadWriteLock + +import com.pivotal.gemfirexd.Constants +import com.pivotal.gemfirexd.internal.engine.Misc +import com.pivotal.gemfirexd.internal.iapi.error.StandardException +import com.pivotal.gemfirexd.internal.shared.common.reference.SQLState +import com.pivotal.gemfirexd.internal.snappy.InterpreterExecute +import io.snappydata.Constant +import io.snappydata.gemxd.SnappySessionPerConnection +import org.apache.spark.Logging +import org.apache.spark.sql.execution.InterpretCodeCommand +import org.apache.spark.sql.execution.columnar.ExternalStoreUtils + +import scala.collection.mutable + +class SnappyInterpreterExecute(sql: String, connId: Long) extends InterpreterExecute with Logging { + + override def execute(user: String, authToken: String): Array[String] = { + if (!SnappyInterpreterExecute.INITIALIZED) SnappyInterpreterExecute.init() + val (allowed, group) = SnappyInterpreterExecute.permissions.isAllowed(user) + if (Misc.isSecurityEnabled && !user.equalsIgnoreCase(SnappyInterpreterExecute.dbOwner)) { + if (!allowed) { + // throw exception + throw StandardException.newException( + SQLState.AUTH_NO_EXECUTE_PERMISSION, user, "scala code execution", "", "ComputeDB", "Cluster") + } + } + val session = SnappySessionPerConnection.getSnappySessionForConnection(connId) + val lp = session.sessionState.sqlParser.parsePlan(sql).asInstanceOf[InterpretCodeCommand] + val interpreterHelper = SnappyInterpreterExecute.getOrCreateStateHolder(connId, user, authToken, group) + interpreterHelper.interpret(lp.code.split("\n")) + } +} + +object SnappyInterpreterExecute { + + private val intpRWLock = new ReentrantReadWriteLock() + private val connToIntpHelperMap = new mutable.HashMap[ + Long, (String, String, RemoteInterpreterStateHolder)] + + private var permissions = new ScalaCodePermissionChecker + + private var INITIALIZED = false + + private lazy val dbOwner = { + Misc.getMemStore.getDatabase.getDataDictionary.getAuthorizationDatabaseOwner.toLowerCase() + } + + def handleNewPermissions(grantor: String, isGrant: Boolean, users: String): Unit = { + if (!Misc.isSecurityEnabled) return + var lockTaken = false + try { + lockTaken = intpRWLock.writeLock().tryLock() + val dbOwner = SnappyInterpreterExecute.dbOwner + if (!grantor.toLowerCase.equals(dbOwner)) { + throw StandardException.newException( + SQLState.AUTH_NO_OBJECT_PERMISSION, grantor, + "grant/revoke of scala code execution", "ComputeDB", "Cluster") + } + val commaSepVals = users.split(",") + commaSepVals.foreach(u => { + if (isGrant) { + // println(s"KN: hnp grantor inside u = $u") + if (u.startsWith(Constants.LDAP_GROUP_PREFIX)) + permissions.addLdapGroup(u) + else permissions.addUser(u) + } else { + if (u.startsWith(Constants.LDAP_GROUP_PREFIX)) + removeAGroupAndCleanup(u) + else removeAUserAndCleanup(u) + } + }) + updatePersistentState + } finally { + if (lockTaken) intpRWLock.writeLock().unlock() + } + } + + private def removeAUserAndCleanup(user: String): Unit = { + permissions.removeUser(user) + val toBeCleanedUpEntries = connToIntpHelperMap.filter( + x => x._2._1.isEmpty && user.equalsIgnoreCase(x._2._2)) + toBeCleanedUpEntries.foreach(x => { + connToIntpHelperMap.remove(x._1) + x._2._3.close() + }) + } + + private def removeAGroupAndCleanup(group: String): Unit = { + permissions.removeLdapGroup(group) + val toBeCleanedUpEntries = connToIntpHelperMap.filter( + x => group.equalsIgnoreCase(x._2._1) + ) + toBeCleanedUpEntries.foreach(x => { + connToIntpHelperMap.remove(x._1) + x._2._3.close() + }) + } + + def refreshOnLdapGroupRefresh(group: String): Unit = { + var lockTaken = false + try { + lockTaken = intpRWLock.writeLock().tryLock() + permissions.refreshOnLdapGroupRefresh(group) + } finally { + if (lockTaken) intpRWLock.writeLock().unlock() + } + } + + private def updatePersistentState = { + Misc.getMemStore.getMetadataCmdRgn.put(Constant.GRANT_REVOKE_KEY, permissions) + } + + def getOrCreateStateHolder(connId: Long, + user: String, authToken: String, group: String): RemoteInterpreterStateHolder = { + var lockTaken = false + try { + lockTaken = intpRWLock.writeLock().tryLock() + connToIntpHelperMap.getOrElse(connId, { + val stateholder = new RemoteInterpreterStateHolder(connId, user, authToken) + connToIntpHelperMap.put(connId, (group, user, stateholder)) + (group, user, stateholder) + })._3 + } finally { + if (lockTaken) intpRWLock.writeLock().unlock() + } + } + + def closeRemoteInterpreter(connId: Long): Unit = { + var lockTaken = false + try { + lockTaken = intpRWLock.writeLock().tryLock() + connToIntpHelperMap.get(connId) match { + case Some(r) => r._3.close() + connToIntpHelperMap.remove(connId) + case None => // Ignore. No interpreter got create for this session. + } + } finally { + if (lockTaken) intpRWLock.writeLock().unlock() + } + } + + private def init(): Unit = { + val key = Constant.GRANT_REVOKE_KEY + val permissionsObj = Misc.getMemStore.getMetadataCmdRgn.get(key) + if (permissionsObj != null) { + permissions = permissionsObj.asInstanceOf[ScalaCodePermissionChecker] + } else { + permissions = new ScalaCodePermissionChecker + } + INITIALIZED = true + } + + private class ScalaCodePermissionChecker extends Serializable { + private val groupToUsersMap: mutable.Map[String, List[String]] = new mutable.HashMap + private val allowedUsers: mutable.ListBuffer[String] = new mutable.ListBuffer[String] + + def isAllowed(user: String): (Boolean, String) = { + if (allowedUsers.contains(user)) return (true, "") + for ((group, list) <- groupToUsersMap) { + if (list.contains(user)) return (true, group) + } + (false, "") + } + + def addUser(user: String): Unit = { + if (!allowedUsers.contains(user)) allowedUsers += user + } + + def removeUser(toBeRemovedUser: String): Unit = { + if (allowedUsers.contains(toBeRemovedUser)) allowedUsers -= toBeRemovedUser + } + + def addLdapGroup(group: String): Unit = { + val grantees = ExternalStoreUtils.getExpandedGranteesIterator(Seq(group)).filterNot( + _.startsWith(Constants.LDAP_GROUP_PREFIX)).map(_.toLowerCase).toList + groupToUsersMap += (group -> grantees) + } + + def removeLdapGroup(toBeRemovedGroup: String): Unit = { + groupToUsersMap.remove(toBeRemovedGroup) + } + + def refreshOnLdapGroupRefresh(group: String): Unit = { + val grantees = ExternalStoreUtils.getExpandedGranteesIterator(Seq(group)).toList + groupToUsersMap.put(group, grantees) + } + } +} diff --git a/cluster/src/main/scala/io/snappydata/tools/SnappyUtilLauncher.scala b/cluster/src/main/scala/io/snappydata/tools/SnappyUtilLauncher.scala index fa911bd42c..f37d409fd0 100644 --- a/cluster/src/main/scala/io/snappydata/tools/SnappyUtilLauncher.scala +++ b/cluster/src/main/scala/io/snappydata/tools/SnappyUtilLauncher.scala @@ -17,12 +17,13 @@ package io.snappydata.tools import java.io.{File, IOException} +import java.nio.file.{Files, Paths} import java.util import com.gemstone.gemfire.internal.GemFireUtilLauncher.{CommandEntry, SCRIPT_NAME} import com.gemstone.gemfire.internal.shared.ClientSharedUtils -import com.gemstone.gemfire.internal.{GemFireTerminateError, GemFireUtilLauncher} -import com.pivotal.gemfirexd.internal.iapi.tools.i18n.LocalizedResource +import com.gemstone.gemfire.internal.{GemFireTerminateError, GemFireUtilLauncher, GemFireVersion} +import com.pivotal.gemfirexd.internal.iapi.tools.i18n.{LocalizedOutput, LocalizedResource} import com.pivotal.gemfirexd.internal.impl.tools.ij.utilMain import com.pivotal.gemfirexd.internal.tools.ij import com.pivotal.gemfirexd.tools.GfxdUtilLauncher.GET_CANONICAL_PATH_ARG @@ -30,8 +31,11 @@ import com.pivotal.gemfirexd.tools.internal.{JarTools, MiscTools} import com.pivotal.gemfirexd.tools.{GfxdSystemAdmin, GfxdUtilLauncher} import io.snappydata.LocalizedMessages import io.snappydata.gemxd.{SnappyDataVersion, SnappySystemAdmin} +import jline.console.ConsoleReader import org.apache.spark.sql.execution.columnar.impl.StoreCallback +import scala.util.Properties.{javaVersion, javaVmName, versionString} + /** * Launcher class encompassing snappy processes command lines. */ @@ -105,6 +109,11 @@ class SnappyUtilLauncher extends GfxdUtilLauncher { object SnappyUtilLauncher extends StoreCallback { + val SNAPPY_SPARK_SHELL = "snappy-scala" + + var INTERPRETER_MODE = false + + var printNewWelcome = false init() private def init(): Unit = { @@ -112,6 +121,11 @@ object SnappyUtilLauncher extends StoreCallback { case s if (s eq null) || s.length == 0 => "snappy" case s => s } + if (SNAPPY_SPARK_SHELL.equals(SCRIPT_NAME)) { + System.setProperty("LAUNCHER_INTERPRETER_MODE", "true") + printNewWelcome = true + INTERPRETER_MODE = true + } } /** @@ -123,9 +137,20 @@ object SnappyUtilLauncher extends StoreCallback { val launcher = new SnappyUtilLauncher() + // TODO: this needs to be switched off because 'exec scala' executes + // scala code and can have a lot of '!' which is treated special by the + // console reader which we don't want. + // Will see if there can be a better workaround. Couldn't find any though + System.setProperty(ConsoleReader.JLINE_EXPAND_EVENTS, "false") + try { // no args will default to using ij - if (args.length == 0) { + if (args.length == 0 || INTERPRETER_MODE) { + if (INTERPRETER_MODE) { + validateIntpArgs(args) + launcher.setInitialCommands( + SnappyUtilLauncher.CONNECT_STR, SnappyUtilLauncher.INITIAL_FILES_TO_RUN_STR) + } launcher.invoke(Array(SCRIPT_NAME)) } // short-circuit for the internal "--get-canonical-path" argument used by @@ -159,4 +184,98 @@ object SnappyUtilLauncher extends StoreCallback { throw re; } } + + val intpUsage = s"\nUsage:\n" + + s"\n${SCRIPT_NAME} [--snappydata.connection|-conn|--connection] [locatorhost:port]" + + s"\n default = locahost:1527\n" + + s"\n [--snappydata.user|-user|--user] [username]" + + s"\n default = APP\n" + + s"\n [--snappydata.password|-passwd|--password] [password of the user]" + + s"\n default = APP\n" + + s"\n [--run|-r|-run] [scala_file_path(s) (comma separated paths if multiple)]" + + s"\n [--help|-help|-h] ['prints the command line options for the script']\n" + + + private def validateArgs(options: Map[Symbol, Any]): Unit = { + val hostport = options.get('connection) match { + case Some(x) => x.toString + case None => "localhost:1527" + } + val user = options.getOrElse('user, "APP") + val passwd = options.getOrElse('password, "APP") + CONNECT_STR = s"connect client '${hostport};user=${user};password=${passwd}'" + val filesToRun = options.get('run) match { + case Some(x) => val files = x.toString + files.split(",").foreach(p => { + val path = Paths.get(p) + if (!Files.exists(path)) { + println(s"File $path does not exists") + System.exit(1) + } + }) + files + case None => "" + } + if (filesToRun.nonEmpty) { + INITIAL_FILES_TO_RUN_STR = filesToRun.toString + } + } + + // expected comma separated files + private var INITIAL_FILES_TO_RUN_STR: String = null + private var CONNECT_STR: String = null; + + private def validateIntpArgs(args: Array[String]): Unit = { + val arglist = args.toList + type ArgsMap = Map[Symbol, Any] + + def isSwitch(s : String) = (s(0) == '-') + + def nextOption(map : ArgsMap, list: List[String]) : ArgsMap = { + + list match { + case Nil => map + case ("--snappydata.connection" | "-conn" | "--connection" ) :: value :: tail => + nextOption(map ++ Map('connection -> value), tail) + case ("--snappydata.user" | "-user" | "--user") :: value :: tail => + nextOption(map ++ Map('user -> value), tail) + case ("--snappydata.password" | "-passwd" | "--password" ) :: value :: tail => + nextOption(map ++ Map('password -> value), tail) + case ("--run" | "-r" | "-run" ) :: value :: tail => + nextOption(map ++ Map('run -> value), tail) + case ("--help" | "-h" | "-help" ) :: tail => + println(intpUsage) + System.exit(0) + Map.empty + case option :: tail => println("\nUnknown or incomplete option " + option) + Map.empty + } + } + + val options = nextOption(Map(),arglist) + if (printNewWelcome) printWelcomeEnterprise() + validateArgs(options) + } + + def printWelcomeEnterprise() { + val version = GemFireVersion.getProductVersion + " " + GemFireVersion.getProductReleaseStage + import org.apache.spark.SPARK_VERSION + // scalastyle:off println + println() + println("""Welcome to + ______ __ ____ ____ + / ____/___ ____ ___ ____ __ __/ /____ / __ \/ __ ) + / / / __ \/ __ `__ \/ __ \/ / / / __/ _ \/ / / / __ | + / /___/ /_/ / / / / / / /_/ / /_/ / /_/ __/ /_/ / /_/ / version %s on Spark version %s + \____/\____/_/ /_/ /_/ .___/\__,_/\__/\___/_____/_____/ + /_/""".format(version, SPARK_VERSION)) + val welcomeMsg = "\nUsing Scala %s (%s, Java %s)".format( + versionString, javaVmName, javaVersion) + println(welcomeMsg) + println() + println("Type in expressions to have them evaluated.\n") + println("Spark context available as 'sc'") + println("Snappy session available as 'snappy'.\n") + // scalastyle:on println + } } diff --git a/core/src/main/scala/io/snappydata/ToolsCallback.scala b/core/src/main/scala/io/snappydata/ToolsCallback.scala index 540a3736de..d52e2de412 100644 --- a/core/src/main/scala/io/snappydata/ToolsCallback.scala +++ b/core/src/main/scala/io/snappydata/ToolsCallback.scala @@ -52,6 +52,8 @@ trait ToolsCallback { def addURIs(alias: String, jars: Array[String], deploySql: String, isPackage: Boolean = true): Unit + def updateIntpGrantRevoke(grantor: String, isGrant: Boolean, users: String): Unit + def removeURIs(uris: Array[String], isPackage: Boolean = true): Unit def addURIsToExecutorClassLoader(jars: Array[String]): Unit @@ -62,7 +64,7 @@ trait ToolsCallback { def getAllGlobalCmnds: Array[String] - def getGlobalCmndsSet: java.util.Set[java.util.Map.Entry[String, String]] + def getGlobalCmndsSet: java.util.Set[java.util.Map.Entry[String, Object]] def removePackage(alias: String): Unit diff --git a/core/src/main/scala/io/snappydata/recovery/RecoveryService.scala b/core/src/main/scala/io/snappydata/recovery/RecoveryService.scala index f5f34a38e4..84b6571690 100644 --- a/core/src/main/scala/io/snappydata/recovery/RecoveryService.scala +++ b/core/src/main/scala/io/snappydata/recovery/RecoveryService.scala @@ -224,10 +224,13 @@ object RecoveryService extends Logging { // view ddls should be at the end so that the extracted ddls won't fail when replayed as is. ddlBuffer.appendAll(tempViewBuffer) - val biConsumer = new BiConsumer[String, String] { - def accept(alias: String, cmd: String): Unit = { + val biConsumer = new BiConsumer[String, Object] { + def accept(alias: String, cmdObj: Object): Unit = { if (!(alias.equals(Constant.CLUSTER_ID) || - alias.startsWith(Constant.MEMBER_ID_PREFIX))) { + alias.startsWith(Constant.MEMBER_ID_PREFIX) || + !cmdObj.isInstanceOf[String])) { + val cmd = cmdObj.asInstanceOf[String] + logInfo("#RecoveryService " + alias + cmd) val cmdFields = cmd.split("\\|", -1) if (cmdFields.length > 1) { val repos = cmdFields(1) diff --git a/core/src/main/scala/org/apache/spark/sql/SnappyBaseParser.scala b/core/src/main/scala/org/apache/spark/sql/SnappyBaseParser.scala index 30f4754800..2ef21b4a5e 100644 --- a/core/src/main/scala/org/apache/spark/sql/SnappyBaseParser.scala +++ b/core/src/main/scala/org/apache/spark/sql/SnappyBaseParser.scala @@ -534,6 +534,7 @@ object SnappyParserConsts { final val DISTRIBUTE: Keyword = nonReservedKeyword("distribute") final val ENABLE: Keyword = nonReservedKeyword("enable") final val END: Keyword = nonReservedKeyword("end") + final val EXEC: Keyword = nonReservedKeyword("exec") final val EXECUTE: Keyword = nonReservedKeyword("execute") final val EXPLAIN: Keyword = nonReservedKeyword("explain") final val EXTENDED: Keyword = nonReservedKeyword("extended") @@ -563,6 +564,7 @@ object SnappyParserConsts { final val RESET: Keyword = nonReservedKeyword("reset") final val RESTRICT: Keyword = nonReservedKeyword("restrict") final val RLIKE: Keyword = nonReservedKeyword("rlike") + final val SCALA: Keyword = nonReservedKeyword("scala") final val SCHEMAS: Keyword = nonReservedKeyword("schemas") final val SEMI: Keyword = nonReservedKeyword("semi") final val SHOW: Keyword = nonReservedKeyword("show") @@ -691,6 +693,7 @@ object SnappyParserConsts { final val PERCENT: Keyword = new Keyword("percent") final val POLICY: Keyword = new Keyword("policy") final val PRIMARY: Keyword = new Keyword("primary") + final val PRIVILEGE: Keyword = new Keyword("privilege") final val PURGE: Keyword = new Keyword("purge") final val PUT: Keyword = new Keyword("put") final val REFRESH: Keyword = new Keyword("refresh") diff --git a/core/src/main/scala/org/apache/spark/sql/SnappyContext.scala b/core/src/main/scala/org/apache/spark/sql/SnappyContext.scala index 730be8902f..8a330bd90d 100644 --- a/core/src/main/scala/org/apache/spark/sql/SnappyContext.scala +++ b/core/src/main/scala/org/apache/spark/sql/SnappyContext.scala @@ -1110,32 +1110,35 @@ object SnappyContext extends Logging { if (deployCmds.length > 0) { logInfo(s"Deployed commands size = ${deployCmds.length}") val commandSet = ToolsCallbackInit.toolsCallback.getGlobalCmndsSet - commandSet.forEach(new Consumer[Entry[String, String]] { - override def accept(t: Entry[String, String]): Unit = { - if (!(t.getKey.equals(Constant.CLUSTER_ID) || + commandSet.forEach(new Consumer[Entry[String, Object]] { + override def accept(t: Entry[String, Object]): Unit = { + if (t.getValue.isInstanceOf[String]) { + if (!(t.getKey.equals(Constant.CLUSTER_ID) || t.getKey.startsWith(Constant.MEMBER_ID_PREFIX) || + t.getKey.equals(Constant.GRANT_REVOKE_KEY) || t.getKey.startsWith(ContextJarUtils.functionKeyPrefix))) { - val d = t.getValue - val cmdFields = d.split('|') // split() removes empty elements - if (d.contains('|')) { - val coordinate = cmdFields(0) - val repos = if (cmdFields.length > 1 && !cmdFields(1).isEmpty) { - Some(cmdFields(1)) - } else None - val cache = if (cmdFields.length > 2 && !cmdFields(2).isEmpty) { - Some(cmdFields(2)) - } else None - try { - DeployCommand(coordinate, null, repos, cache, restart = true) + val d = t.getValue.toString + val cmdFields = d.split('|') // split() removes empty elements + if (d.contains('|')) { + val coordinate = cmdFields(0) + val repos = if (cmdFields.length > 1 && !cmdFields(1).isEmpty) { + Some(cmdFields(1)) + } else None + val cache = if (cmdFields.length > 2 && !cmdFields(2).isEmpty) { + Some(cmdFields(2)) + } else None + try { + DeployCommand(coordinate, null, repos, cache, restart = true) .run(session) - } catch { - case e: Throwable => failOnJarUnavailability(t.getKey, Array.empty, e) - } - } else { // Jars we have - try { - DeployJarCommand(null, cmdFields(0), restart = true).run(session) - } catch { - case e: Throwable => failOnJarUnavailability(t.getKey, cmdFields, e) + } catch { + case e: Throwable => failOnJarUnavailability(t.getKey, Array.empty, e) + } + } else { // Jars we have + try { + DeployJarCommand(null, cmdFields(0), restart = true).run(session) + } catch { + case e: Throwable => failOnJarUnavailability(t.getKey, cmdFields, e) + } } } } diff --git a/core/src/main/scala/org/apache/spark/sql/SnappyDDLParser.scala b/core/src/main/scala/org/apache/spark/sql/SnappyDDLParser.scala index 8eeb99bac9..40ce3c8da8 100644 --- a/core/src/main/scala/org/apache/spark/sql/SnappyDDLParser.scala +++ b/core/src/main/scala/org/apache/spark/sql/SnappyDDLParser.scala @@ -19,16 +19,10 @@ package org.apache.spark.sql import java.io.File -import scala.util.Try - import com.pivotal.gemfirexd.internal.engine.Misc -import com.pivotal.gemfirexd.internal.iapi.sql.dictionary.SchemaDescriptor import com.pivotal.gemfirexd.internal.iapi.util.IdUtil import io.snappydata.sql.catalog.{CatalogObjectType, SnappyExternalCatalog} import io.snappydata.{Constant, Property, QueryHint} -import org.parboiled2._ -import shapeless.{::, HNil} - import org.apache.spark.sql.SnappyParserConsts.plusOrMinus import org.apache.spark.sql.catalyst.catalog.{BucketSpec, CatalogTableType, FunctionResource, FunctionResourceType} import org.apache.spark.sql.catalyst.expressions._ @@ -46,6 +40,10 @@ import org.apache.spark.sql.streaming.StreamPlanProvider import org.apache.spark.sql.types._ import org.apache.spark.sql.{SnappyParserConsts => Consts} import org.apache.spark.streaming._ +import org.parboiled2._ +import shapeless.{::, HNil} + +import scala.util.Try abstract class SnappyDDLParser(session: SnappySession) extends SnappyBaseParser(session) { @@ -137,6 +135,7 @@ abstract class SnappyDDLParser(session: SnappySession) final def DISKSTORE: Rule0 = rule { keyword(Consts.DISKSTORE) } final def ENABLE: Rule0 = rule { keyword(Consts.ENABLE) } final def END: Rule0 = rule { keyword(Consts.END) } + final def EXEC: Rule0 = rule { keyword(Consts.EXEC) } final def EXECUTE: Rule0 = rule { keyword(Consts.EXECUTE) } final def EXPLAIN: Rule0 = rule { keyword(Consts.EXPLAIN) } final def EXTENDED: Rule0 = rule { keyword(Consts.EXTENDED) } @@ -185,6 +184,7 @@ abstract class SnappyDDLParser(session: SnappySession) final def PERCENT: Rule0 = rule { keyword(Consts.PERCENT) } final def POLICY: Rule0 = rule { keyword(Consts.POLICY) } final def PRIMARY: Rule0 = rule { keyword(Consts.PRIMARY) } + final def PRIVILEGE: Rule0 = rule { keyword(Consts.PRIVILEGE) } final def PURGE: Rule0 = rule { keyword(Consts.PURGE) } final def PUT: Rule0 = rule { keyword(Consts.PUT) } final def REFRESH: Rule0 = rule { keyword(Consts.REFRESH) } @@ -196,6 +196,7 @@ abstract class SnappyDDLParser(session: SnappySession) final def RESTRICT: Rule0 = rule { keyword(Consts.RESTRICT) } final def RETURNS: Rule0 = rule { keyword(Consts.RETURNS) } final def RLIKE: Rule0 = rule { keyword(Consts.RLIKE) } + final def SCALA: Rule0 = rule { keyword(Consts.SCALA) } final def SCHEMAS: Rule0 = rule { keyword(Consts.SCHEMAS) } final def SECURITY: Rule0 = rule { keyword(Consts.SECURITY) } final def SEMI: Rule0 = rule { keyword(Consts.SEMI) } @@ -470,6 +471,38 @@ abstract class SnappyDDLParser(session: SnappySession) new StringBuilder().append(s))) ~ tableEnd1 } + /** + * INTP options (...) code { ...... } + * @return LogicalPlan + */ + protected def interpretCode: Rule1[LogicalPlan] = rule { + EXEC ~ ws ~ SCALA ~ ws ~ (OPTIONS ~ options ~ ws).? ~ codeChunk ~> { + ( opts: Any, code: String) => + val parameters = opts.asInstanceOf[Option[Map[String, String]]] + .getOrElse(Map.empty[String, String]) + + InterpretCodeCommand(code, parameters) + } + } + + protected def grantRevokeIntp: Rule1[LogicalPlan] = rule { + GRANT ~ ws ~ PRIVILEGE ~ ws ~ EXEC ~ ws ~ SCALA ~ ws ~ TO ~ + ws ~ capture(ANY.*) ~> { + (users: String) => GrantRevokeIntpCommand(true, users) } | + REVOKE ~ ws ~ PRIVILEGE ~ ws ~ EXEC ~ ws ~ SCALA ~ ws ~ FROM ~ + ws ~ capture(ANY.*) ~> { + (users: String) => GrantRevokeIntpCommand(false, users) + } + } + + protected def codeChunk: Rule1[String] = rule { + capture(ANY.*) ~ EOI ~> ((code : String) => code ) + /*** + '{' ~ capture(ANY) ~ '}' ~> ((code : String) => code ) + ***/ + } + + protected def createIndex: Rule1[LogicalPlan] = rule { (CREATE ~ (GLOBAL ~ HASH ~ push(false) | UNIQUE ~ push(true)).? ~ INDEX) ~ tableIdentifier ~ ON ~ tableIdentifier ~ @@ -988,7 +1021,7 @@ abstract class SnappyDDLParser(session: SnappySession) dropTable | truncateTable | createView | createTempViewUsing | dropView | alterView | createSchema | dropSchema | alterTableToggleRowLevelSecurity | createPolicy | dropPolicy | alterTableProps | alterTableOrView | alterTable | createStream | streamContext | - createIndex | dropIndex | createFunction | dropFunction | passThrough) + createIndex | dropIndex | createFunction | dropFunction | grantRevokeIntp | passThrough | interpretCode ) } protected def partitionSpec: Rule1[Map[String, Option[String]]] diff --git a/core/src/main/scala/org/apache/spark/sql/execution/ddl.scala b/core/src/main/scala/org/apache/spark/sql/execution/ddl.scala index 50c28fa013..bfa4b6d8b1 100644 --- a/core/src/main/scala/org/apache/spark/sql/execution/ddl.scala +++ b/core/src/main/scala/org/apache/spark/sql/execution/ddl.scala @@ -18,7 +18,6 @@ package org.apache.spark.sql.execution import java.io.File -import java.lang import java.nio.file.{Files, Paths} import java.util.Map.Entry import java.util.function.Consumer @@ -53,6 +52,45 @@ import org.apache.spark.storage.StorageLevel import org.apache.spark.streaming.{Duration, SnappyStreamingContext} import org.apache.spark.unsafe.types.CalendarInterval +import scala.tools.nsc.{GenericRunnerSettings, Settings} +import scala.tools.nsc.interpreter.IMain + + +/** + * Allow execution of adhoc scala code on the Lead node. + * Creates a new Scala interpreter for a Snappy Session. But, cached for the life of the + * session. Subsequent invocations of the 'interpret' command will resuse the cached + * interpreter. Allowing any variables (e.g. dataframe) to be preserved across invocations. + * State will not be preserved during Lead node failover. + *

Application is injected (1) The SnappySession in variable called 'session' and + * (2) The Options in a variable called 'intp_options'. + *

To return values set a variable called 'intp_return' - a Seq[Row]. + */ +case class InterpretCodeCommand( + code: String, + options: Map[String, String]) extends RunnableCommand { + + // This is handled directly by Remote Interpreter code + override def run(sparkSession: SparkSession): Seq[Row] = Nil +} + +case class GrantRevokeIntpCommand( + isGrant: Boolean, users: String) extends RunnableCommand { + + // This is handled directly by Remote Interpreter code + override def run(sparkSession: SparkSession): Seq[Row] = { + val tcb = ToolsCallbackInit.toolsCallback + if (tcb == null) { + throw new AnalysisException("Granting/Revoking" + + " of INTP not supported from smart connector mode"); + } + val session = sparkSession.asInstanceOf[SnappySession] + val user = session.conf.get(com.pivotal.gemfirexd.Attribute.USERNAME_ATTR) + tcb.updateIntpGrantRevoke(user, isGrant, users) + Nil + } +} + case class CreateTableUsingCommand( tableIdent: TableIdentifier, baseTable: Option[String], @@ -557,8 +595,8 @@ case class ListPackageJarsCommand(isJar: Boolean) extends RunnableCommand { override def run(sparkSession: SparkSession): Seq[Row] = { val commands = ToolsCallbackInit.toolsCallback.getGlobalCmndsSet val rows = new ArrayBuffer[Row] - commands.forEach(new Consumer[Entry[String, String]] { - override def accept(t: Entry[String, String]): Unit = { + commands.forEach(new Consumer[Entry[String, Object]] { + override def accept(t: Entry[String, Object]): Unit = { if (!(t.getKey.equals(Constant.CLUSTER_ID) || t.getKey.startsWith(Constant.MEMBER_ID_PREFIX))) { var alias = t.getKey @@ -566,25 +604,27 @@ case class ListPackageJarsCommand(isJar: Boolean) extends RunnableCommand { if (alias.contains(ContextJarUtils.droppedFunctionsKey)) return // Explicitly mark functions as UDF while listing jars/packages. alias = alias.replace(ContextJarUtils.functionKeyPrefix, "[UDF]") - val value = t.getValue - val indexOf = value.indexOf('|') - if (indexOf > 0) { - // It is a package - val pkg = value.substring(0, indexOf) - rows += Row(alias, pkg, true) - } - else { - // It is a jar - val jars = value.split(',') - val jarfiles = jars.map(f => { - val lastIndexOf = f.lastIndexOf('/') - val length = f.length - if (lastIndexOf > 0) f.substring(lastIndexOf + 1, length) - else { - f - } - }) - rows += Row(alias, jarfiles.mkString(","), false) + if (t.getValue.isInstanceOf[String]) { + val value = t.getValue.toString + val indexOf = value.indexOf('|') + if (indexOf > 0) { + // It is a package + val pkg = value.substring(0, indexOf) + rows += Row(alias, pkg, true) + } + else { + // It is a jar + val jars = value.split(',') + val jarfiles = jars.map(f => { + val lastIndexOf = f.lastIndexOf('/') + val length = f.length + if (lastIndexOf > 0) f.substring(lastIndexOf + 1, length) + else { + f + } + }) + rows += Row(alias, jarfiles.mkString(","), false) + } } } } @@ -600,33 +640,35 @@ case class UnDeployCommand(alias: String) extends RunnableCommand { val sc = sparkSession.sparkContext if (alias != null) { val cmndsSet = ToolsCallbackInit.toolsCallback.getGlobalCmndsSet - cmndsSet.forEach(new Consumer[Entry[String, String]] { - override def accept(t: Entry[String, String]): Unit = { + cmndsSet.forEach(new Consumer[Entry[String, Object]] { + override def accept(t: Entry[String, Object]): Unit = { val alias1 = t.getKey if (alias == alias1) { - value = t.getValue + value = if (t.getValue.isInstanceOf[String]) t.getValue.asInstanceOf[String] else null } } }) - val indexOf = value.indexOf("|") - val lastIndexOf = value.lastIndexOf("|") - if (indexOf > 0) { - val coordinates = value.substring(0, indexOf) - val repos = Option(value.substring(indexOf + 1, lastIndexOf)) - val jarCache = Option(value.substring(lastIndexOf + 1, value.length)) - val jarsstr = SparkSubmitUtils.resolveMavenCoordinates(coordinates, - repos, jarCache) - if (jarsstr.nonEmpty) { - val pkgs = jarsstr.split(",") - RefreshMetadata.executeOnAll(sc, RefreshMetadata.REMOVE_URIS_FROM_CLASSLOADER, pkgs) - ToolsCallbackInit.toolsCallback.removeURIs(pkgs) + if (value != null) { + val indexOf = value.indexOf("|") + val lastIndexOf = value.lastIndexOf("|") + if (indexOf > 0) { + val coordinates = value.substring(0, indexOf) + val repos = Option(value.substring(indexOf + 1, lastIndexOf)) + val jarCache = Option(value.substring(lastIndexOf + 1, value.length)) + val jarsstr = SparkSubmitUtils.resolveMavenCoordinates(coordinates, + repos, jarCache) + if (jarsstr.nonEmpty) { + val pkgs = jarsstr.split(",") + RefreshMetadata.executeOnAll(sc, RefreshMetadata.REMOVE_URIS_FROM_CLASSLOADER, pkgs) + ToolsCallbackInit.toolsCallback.removeURIs(pkgs) + } } - } - else { - if (value.nonEmpty) { - val jars = value.split(',') - RefreshMetadata.executeOnAll(sc, RefreshMetadata.REMOVE_URIS_FROM_CLASSLOADER, jars) - ToolsCallbackInit.toolsCallback.removeURIs(jars) + else { + if (value.nonEmpty) { + val jars = value.split(',') + RefreshMetadata.executeOnAll(sc, RefreshMetadata.REMOVE_URIS_FROM_CLASSLOADER, jars) + ToolsCallbackInit.toolsCallback.removeURIs(jars) + } } } } @@ -701,3 +743,4 @@ case class PutIntoValuesColumnTable(db: String, tableName: String, } } } + diff --git a/core/src/main/scala/org/apache/spark/sql/internal/JarUtils.scala b/core/src/main/scala/org/apache/spark/sql/internal/JarUtils.scala index 19ff020c81..fbc7a3cedd 100644 --- a/core/src/main/scala/org/apache/spark/sql/internal/JarUtils.scala +++ b/core/src/main/scala/org/apache/spark/sql/internal/JarUtils.scala @@ -155,9 +155,10 @@ object ContextJarUtils extends Logging { def addToTheListInCmdRegion(k: String, item: String, head: String): Unit = { val r = Misc.getMemStore.getMetadataCmdRgn var old1: String = null - var old2: String = null + var old2: AnyRef = null do { - old1 = r.get(k) + val oldObj = r.get(k) + old1 = if ( oldObj != null ) oldObj.asInstanceOf[String] else null val newValue = if (old1 != null) old1 + item else head + item old2 = r.put(k, newValue) } while (old1 != old2) @@ -166,19 +167,23 @@ object ContextJarUtils extends Logging { def removeFromTheListInCmdRegion(k: String, item: String): Unit = { val r = Misc.getMemStore.getMetadataCmdRgn var old1: String = null - var old2: String = null + var old2: AnyRef = null do { - old1 = r.get(k) - if (old1 != null) { - val newValue = old1.replace(item, "") + val oldObj = r.get(k) + if (oldObj != null) { + val newValue = oldObj.asInstanceOf[String].replace(item, "") old2 = r.put(k, newValue) } } while (old1 != old2) } def checkItemExists(k: String, item: String): Boolean = { - val value = Misc.getMemStore.getMetadataCmdRgn.get(k) - value != null && value.contains(item) + var value = Misc.getMemStore.getMetadataCmdRgn.get(k) + if (value != null) { + val valueStr = value.asInstanceOf[String] + return valueStr.contains(item) + } + false } } diff --git a/jdbc/src/main/scala/io/snappydata/Constant.scala b/jdbc/src/main/scala/io/snappydata/Constant.scala index b560f26286..4251de5107 100644 --- a/jdbc/src/main/scala/io/snappydata/Constant.scala +++ b/jdbc/src/main/scala/io/snappydata/Constant.scala @@ -168,4 +168,6 @@ object Constant { val CLUSTER_ID = "__cluster_id__" val MEMBER_ID_PREFIX = "__member_id__" + + val GRANT_REVOKE_KEY = "##_INTP__GRANT__REVOKE_##" } From b7da064459d72d012bab352857d592be51841864 Mon Sep 17 00:00:00 2001 From: Neeraj Kumar Date: Sat, 23 Nov 2019 15:51:49 +0530 Subject: [PATCH 011/101] linking latest store and spark-jobserver with snappydata repo. --- spark-jobserver | 2 +- store | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/spark-jobserver b/spark-jobserver index d6ca632810..9ee48b2162 160000 --- a/spark-jobserver +++ b/spark-jobserver @@ -1 +1 @@ -Subproject commit d6ca632810d8b032c1a6a6baa783e04ed8433bb5 +Subproject commit 9ee48b2162d12a1a565a1aedf7580b72e3181455 diff --git a/store b/store index fc72d44900..830eb72bac 160000 --- a/store +++ b/store @@ -1 +1 @@ -Subproject commit fc72d44900ce68e25c0dd1bd9a63e5339cbc1f06 +Subproject commit 830eb72baccaa79bd99e71707b59969576ea8b72 From 224992c3a8fd1b146debe70eafd981f233c2aac6 Mon Sep 17 00:00:00 2001 From: Neeraj Kumar Date: Sat, 23 Nov 2019 16:17:21 +0530 Subject: [PATCH 012/101] link the store repo. --- store | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/store b/store index 830eb72bac..68d5ead5f6 160000 --- a/store +++ b/store @@ -1 +1 @@ -Subproject commit 830eb72baccaa79bd99e71707b59969576ea8b72 +Subproject commit 68d5ead5f6b15c4c2e8b19ba6584b0f4a57fe85b From 19105f9c4b57e2c3e563f463a222a9a2046a1e7e Mon Sep 17 00:00:00 2001 From: Shirish Deshmukh Date: Mon, 25 Nov 2019 12:33:50 +0530 Subject: [PATCH 013/101] Fix for snap-3163 (#1477) [SNAP-3163] SQL plan display wrong in connector mode When smart connector is used, SnappySQLListsner is not being initialized (in SnappySharedState#createListenerAndUI) and instead Spark initialized SQLListener instance. Due to this, Snappy specific events like SparkListenerSQLPlanExecutionStart fired from SnappySession#planExecution to record metrics are being ignored. As a fix in smart connector mode, replacing SQLListener instance with SnappySQLListener and copying the contents from the SQLListener to SnappySQLListener so that the information recorded in it is not lost --- .../spark/sql/internal/SnappySharedState.java | 25 +++++++++++ .../sql/execution/ui/SnappySQLListener.scala | 42 ++++++++++++++++++- 2 files changed, 65 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/org/apache/spark/sql/internal/SnappySharedState.java b/core/src/main/java/org/apache/spark/sql/internal/SnappySharedState.java index 1bf1156e01..8ad9fa4a92 100644 --- a/core/src/main/java/org/apache/spark/sql/internal/SnappySharedState.java +++ b/core/src/main/java/org/apache/spark/sql/internal/SnappySharedState.java @@ -38,6 +38,7 @@ import org.apache.spark.sql.hive.SnappyHiveExternalCatalog; import org.apache.spark.storage.StorageLevel; import org.apache.spark.ui.SparkUI; +import org.apache.spark.ui.WebUITab; /** * Overrides Spark's SharedState to enable setting up own ExternalCatalog. @@ -119,6 +120,30 @@ private static void createListenerAndUI(SparkContext sc) { new SQLTab(listener, ui.get()); } } + } else if (!(initListener instanceof SnappySQLListener) && + !(SnappyContext.getClusterMode(sc) instanceof SnappyEmbeddedMode)) { + // In smart connector mode, initListener could be an instance SQLListener instead of + // SnappySQLListener if initialized by Spark in SharedState.createListenerAndUI. We replace + // it with instance of SnappySQLListener and copy the contents from the initListener to + // SnappySQLListener so that the information recorded in initListener is not lost + replaceSQLListener(sc, initListener); + } + } + + private static void replaceSQLListener(SparkContext sc, SQLListener originalListener) { + SnappySQLListener listener = new SnappySQLListener(sc.conf(), originalListener); + if (ExternalStoreUtils.getSQLListener().compareAndSet(originalListener, listener)) { + sc.addSparkListener(listener); + sc.listenerBus().removeListener(originalListener); + scala.Option ui = sc.ui(); + if (ui.isDefined()) { + scala.collection.Iterator iter = ui.get().getTabs().iterator(); + while (iter.hasNext()) { + WebUITab tab = (WebUITab)iter.next(); + if (tab instanceof SQLTab) ui.get().detachTab(tab); + } + new SQLTab(listener, ui.get()); + } } } diff --git a/core/src/main/scala/org/apache/spark/sql/execution/ui/SnappySQLListener.scala b/core/src/main/scala/org/apache/spark/sql/execution/ui/SnappySQLListener.scala index 4a20156e52..7ac3a27443 100644 --- a/core/src/main/scala/org/apache/spark/sql/execution/ui/SnappySQLListener.scala +++ b/core/src/main/scala/org/apache/spark/sql/execution/ui/SnappySQLListener.scala @@ -44,27 +44,65 @@ case class SparkListenerSQLPlanExecutionEnd(executionId: Long) extends SparkList */ class SnappySQLListener(conf: SparkConf) extends SQLListener(conf) { + var sourceListener: SQLListener = _ + // constructor that copies contents of source listener into this listener + // used in smart connector + def this(conf: SparkConf, source: SQLListener) { + this(conf) + if (source != null) { + sourceListener = source + copyDataFromSourceListener() + } + } + // base class variables that are private private[this] val baseStageIdToStageMetrics = { getInternalField("org$apache$spark$sql$execution$ui$SQLListener$$_stageIdToStageMetrics"). asInstanceOf[mutable.HashMap[Long, SQLStageMetrics]] } + private[this] val baseJobIdToExecutionId = { getInternalField("org$apache$spark$sql$execution$ui$SQLListener$$_jobIdToExecutionId"). asInstanceOf[mutable.HashMap[Long, Long]] } + private[this] val baseActiveExecutions = { getInternalField("activeExecutions").asInstanceOf[mutable.HashMap[Long, SQLExecutionUIData]] } + private[this] val baseExecutionIdToData = { getInternalField("org$apache$spark$sql$execution$ui$SQLListener$$_executionIdToData"). asInstanceOf[mutable.HashMap[Long, SQLExecutionUIData]] } - def getInternalField(fieldName: String): Any = { + private[this] val baseFailedExecutions = { + getInternalField("org$apache$spark$sql$execution$ui$SQLListener$$failedExecutions"). + asInstanceOf[mutable.ListBuffer[SQLExecutionUIData]] + } + + private[this] val baseCompletedExecutions = { + getInternalField("org$apache$spark$sql$execution$ui$SQLListener$$completedExecutions"). + asInstanceOf[mutable.ListBuffer[SQLExecutionUIData]] + } + + def getInternalField(fieldName: String, listenerObject: SQLListener = this): Any = { val resultField = classOf[SQLListener].getDeclaredField(fieldName) resultField.setAccessible(true) - resultField.get(this) + resultField.get(listenerObject) + } + + // copy the contents from source listener to this listener + def copyDataFromSourceListener() { + baseStageIdToStageMetrics ++= sourceListener.stageIdToStageMetrics + baseJobIdToExecutionId ++= sourceListener.jobIdToExecutionId + baseExecutionIdToData ++= sourceListener.executionIdToData + baseFailedExecutions ++= sourceListener.getFailedExecutions + baseCompletedExecutions ++= sourceListener.getCompletedExecutions + + // get by reflection since no getter is available + var sourceActiveExecutions = getInternalField("activeExecutions", sourceListener). + asInstanceOf[mutable.HashMap[Long, SQLExecutionUIData]] + baseActiveExecutions ++= sourceActiveExecutions } override def onJobStart(jobStart: SparkListenerJobStart): Unit = { From bfb1350fb2497d744595fe77e413cd53c287a822 Mon Sep 17 00:00:00 2001 From: Neeraj Kumar Date: Mon, 25 Nov 2019 15:29:54 +0530 Subject: [PATCH 014/101] Minor fix to show output in sepatate lines in zeppelin --- .../remote/interpreter/SnappyInterpreterExecute.scala | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cluster/src/main/scala/io/snappydata/remote/interpreter/SnappyInterpreterExecute.scala b/cluster/src/main/scala/io/snappydata/remote/interpreter/SnappyInterpreterExecute.scala index 4c9e82e079..7f5436cde0 100644 --- a/cluster/src/main/scala/io/snappydata/remote/interpreter/SnappyInterpreterExecute.scala +++ b/cluster/src/main/scala/io/snappydata/remote/interpreter/SnappyInterpreterExecute.scala @@ -49,7 +49,9 @@ class SnappyInterpreterExecute(sql: String, connId: Long) extends InterpreterExe val session = SnappySessionPerConnection.getSnappySessionForConnection(connId) val lp = session.sessionState.sqlParser.parsePlan(sql).asInstanceOf[InterpretCodeCommand] val interpreterHelper = SnappyInterpreterExecute.getOrCreateStateHolder(connId, user, authToken, group) - interpreterHelper.interpret(lp.code.split("\n")) + val outputLines = interpreterHelper.interpret(lp.code.split("\n")) + if (outputLines != null && outputLines.nonEmpty) outputLines.flatMap(_.split("\n")) + else outputLines } } From 8f65f30eb4a2ffbbd31e202f0a15c1997cb5476f Mon Sep 17 00:00:00 2001 From: Neeraj Kumar Date: Mon, 25 Nov 2019 15:50:47 +0530 Subject: [PATCH 015/101] snappysession should not be cleared when interpreter is reset as that will be done when the session closes. --- .../remote/interpreter/RemoteInterpreterStateHolder.scala | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cluster/src/main/scala/io/snappydata/remote/interpreter/RemoteInterpreterStateHolder.scala b/cluster/src/main/scala/io/snappydata/remote/interpreter/RemoteInterpreterStateHolder.scala index 803ac8d3e5..5b2a0bfcee 100644 --- a/cluster/src/main/scala/io/snappydata/remote/interpreter/RemoteInterpreterStateHolder.scala +++ b/cluster/src/main/scala/io/snappydata/remote/interpreter/RemoteInterpreterStateHolder.scala @@ -162,7 +162,8 @@ class RemoteInterpreterStateHolder(val connId: Long, val user: String, val authT intp.close() strOpStream.close() pw.close() - snappy.clear() + // let the session close handle snappy clear. + // snappy.clear() incomplete.setLength(0) allInterpretedLinesForReplay.clear() } From 9984991b75efc1c1a11242686fd02e562abdad84 Mon Sep 17 00:00:00 2001 From: ahshahid Date: Mon, 25 Nov 2019 14:29:26 -0800 Subject: [PATCH 016/101] possible fix for sporadic big view test failure --- cluster/src/test/scala/org/apache/spark/sql/store/BugTest.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cluster/src/test/scala/org/apache/spark/sql/store/BugTest.scala b/cluster/src/test/scala/org/apache/spark/sql/store/BugTest.scala index cd6104b15b..9ef4e88fae 100644 --- a/cluster/src/test/scala/org/apache/spark/sql/store/BugTest.scala +++ b/cluster/src/test/scala/org/apache/spark/sql/store/BugTest.scala @@ -407,7 +407,7 @@ class BugTest extends SnappyFunSuite with BeforeAndAfterAll { var foundValidColumnName = false while(rs.next() && !foundValidColumnName) { val colName = rs.getString("COLUMN_NAME") - if (colName == "yeari") { + if (colName.equalsIgnoreCase("yeari")) { foundValidColumnName = true } } From 79c8057cd09756ea09848fca5fd5664faee3ce67 Mon Sep 17 00:00:00 2001 From: Amogh Shetkar Date: Tue, 26 Nov 2019 20:17:05 +0530 Subject: [PATCH 017/101] Community docv1.1.1 temp2 (#1485) * Changes to Docker topic, AWS topic, Hadoop provided settings section and mkdocs. --- .../configuring_cluster.md | 2 + ...tting_up_cluster_on_amazon_web_services.md | 134 ++++++++------ .../getting_started_with_docker_image.md | 171 +++++++++++++++--- mkdocs.yml | 6 +- 4 files changed, 228 insertions(+), 85 deletions(-) diff --git a/docs/configuring_cluster/configuring_cluster.md b/docs/configuring_cluster/configuring_cluster.md index 3bd09dd25c..da2f78b6bb 100644 --- a/docs/configuring_cluster/configuring_cluster.md +++ b/docs/configuring_cluster/configuring_cluster.md @@ -251,6 +251,7 @@ $ ./bin/spark-submit --deploy-mode cluster --class somePackage.someClass Any Spark or SnappyData specific environment settings can be done by creating a **snappy-env.sh** or **spark-env.sh** in **SNAPPY_HOME/conf**. + ## Logging diff --git a/docs/install/setting_up_cluster_on_amazon_web_services.md b/docs/install/setting_up_cluster_on_amazon_web_services.md index b4a1cbc13a..aba8b9bf3b 100644 --- a/docs/install/setting_up_cluster_on_amazon_web_services.md +++ b/docs/install/setting_up_cluster_on_amazon_web_services.md @@ -154,7 +154,7 @@ For more information, refer to the [Apache Zeppelin](#LoggingZeppelin) section o ## SnappyData EC2 Scripts -The SnappyData EC2 scripts enable you to quickly launch and manage SnappyData clusters on Amazon EC2 instances. They also allow you to provide custom configuration for the cluster via SnappyData configuration files, before launching the cluster. +The SnappyData EC2 scripts enable you to launch and manage SnappyData clusters quickly on Amazon EC2 instances. They also allow you to provide custom configuration for the cluster via SnappyData configuration files, before launching the cluster. The `snappy-ec2` script is the entry point for these EC2 scripts and is derived from the `spark-ec2` script available in [Apache Spark 1.6](https://github.com/apache/spark/tree/branch-1.6/ec2). @@ -202,9 +202,9 @@ aws/ec2 directory where the [SnappyData cloud tools repository](https://github.c Here: -* `` refers to the EC2 key pair. +* `` refers to the name of your EC2 key pair. -* `` refers to the path to the key file. +* `` refers to the path to the key (typically .pem) file. * `` refers to the action to be performed. Some of the available actions are `launch`, `destroy`, `stop`, `start` and `reboot-cluster`. Use `launch` action to create a new cluster while `stop` and `start` actions work on existing clusters. @@ -245,7 +245,7 @@ An IAM user in AWS can gain additional (or different) permissions, or get permis **Example** ``` --./snappy-ec2 -k -i stop snap_ec2_cluster --with-zeppelin --authorized-address= --assume-role-arn= --assume-role-timeout= --assume-role-session-name= +./snappy-ec2 -k -i stop snap_ec2_cluster --with-zeppelin --authorized-address= --assume-role-arn= --assume-role-timeout= --assume-role-session-name= ``` !!! Note @@ -273,7 +273,7 @@ This section covers the following: This script by default uses the SnappyData OSS build available on the GitHub releases page to launch the cluster. To select a version of the OSS build available on GitHub, use option `--snappydata-version`. -You can also provide your own SnappyData build to the script to launch the cluster, by using +You can also provide your SnappyData build to the script to launch the cluster, by using option `--snappydata-tarball` to the `launch` command. The build can be present either on a local filesystem or as a resource on the web. @@ -294,8 +294,8 @@ The build file should be in **.tar.gz** format. #### Specifying Properties -You can specify the configuration for the cluster via command line options. Use `--locator-conf` to specify the -configuration properties for all the locators in the cluster. Similarly, `--server-conf` and `--lead-conf` allow you +You can specify the configuration for the cluster via command-line options. Use `--locator-conf` to specify the +configuration properties for all the locators in the cluster. Similarly, `--server-conf` and `--lead-conf` allows you to specify the configuration properties for servers and leads in the cluster, respectively. Following is a sample configuration for all the three processes in a SnappyData cluster: @@ -310,15 +310,13 @@ Following is a sample configuration for all the three processes in a SnappyData The utility also reads **snappy-env.sh**, if present in the directory where helper scripts are present. !!! Note - * The earlier method of specifying the configuration properties by placing the actual - configuration files in the directory, where helper scripts are available, is discontinued. - * Ensure that the configuration properties specified are correct. Otherwise, launching the - SnappyData cluster may fail but the EC2 instances would still be running. + * The earlier method of specifying the configuration properties by placing the actual configuration files in the directory, where helper scripts are available, is discontinued. + * Ensure that the configuration properties specified are correct. Otherwise, launching the SnappyData cluster may fail, but the EC2 instances would still be running. #### Stopping the Cluster -When you stop a cluster, it shuts down the EC2 instances and any data saved on the local instance stores is lost. +When you stop a cluster, it shuts down the EC2 instances, and any data saved on the local instance stores is lost. However, the data saved on EBS volumes is retained, unless the spot-instances are used. ```pre @@ -372,7 +370,7 @@ This also deletes the security groups created for this cluster. #### Starting Cluster with Apache Zeppelin -Optionally, you can start an instance of Apache Zeppelin server with the cluster. +Optionally, you can start an instance of the Apache Zeppelin server with the cluster. [Apache Zeppelin](https://zeppelin.apache.org/) provides a web-based interactive notebook that is pre-configured to communicate with the SnappyData cluster. The Zeppelin server is launched on the same EC2 instance where the lead node is running. @@ -382,7 +380,7 @@ communicate with the SnappyData cluster. The Zeppelin server is launched on the #### More Options -For a complete list of options provided by the script, simply run `./snappy-ec2`. The options are also provided below +For a complete list of options provided by the script, run `./snappy-ec2`. The options are also provided below for quick reference. @@ -523,23 +521,26 @@ Options: ## AWS Management Console -!!! Attention - The AMIs of SnappyData release 1.1.0 onwards are not available on AWS. - -You can launch a SnappyData cluster on Amazon EC2 instance(s) using the AMI provided by SnappyData. For more information +You can launch a SnappyData cluster on Amazon EC2 instance(s) using Linux-based AMIs available on AWS. For more information on launching an EC2 instance, refer to the [AWS documentation](http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/launching-instance.html). This section covers the following: * [Prerequisites](#prereqaws) -* [Launching the Instance](#launchawsinstance) +* [Launching the Instance and Cluster](#launchawsinstance) +* [Accessing the Cluster](#accesssnappydatacluster) + +!!! Attention + The AMIs of SnappyData are currently unavailable on AWS. + ### Prerequisites -Ensure that you have an existing AWS account with required permissions to launch the EC2 resources. +* Ensure that you have an existing AWS account with required permissions to launch the EC2 resources. +* Create an EC2 Key Pair in the region where you want to launch the SnappyData cluster. ### Deploying SnappyData Cluster with AWS Management Console -To launch the instance and start the SnappyData cluster: +To launch the instance and start the SnappyData cluster on a single EC2 instance: 1. Open the [Amazon EC2 console](https://console.aws.amazon.com/ec2/) and sign in using your AWS login credentials. @@ -547,84 +548,101 @@ To launch the instance and start the SnappyData cluster: 3. Click **Launch Instance** from the Amazon EC2 console dashboard. -4. On the **Choose an Amazon Machine Image (AMI)** page, select **Community AMIs** from the left pane. - -5. Enter **SnappyData** in the search box, and press **Enter** on your keyboard. - -6. The search result is displayed. From the search results, click **Select** to choose the AMI with the latest release version. +4. On the **Choose an Amazon Machine Image (AMI)** page, select your preferred Linux-based AMI. For example, you can select **Amazon Linux 2 AMI** or **Ubuntu Server 16.04 LTS**. See [this page](./system_requirements.md#operating-systems-supported) for recommended Operating Systems. - * If you do not see the AMI with the latest or required version of SnappyData, you can select a standard Linux AMI of appropriate version (for example, Amazon Linux 2018.03). We'll setup SnappyData manually on this instance in later steps. + * The AMIs with pre-installed SnappyData distribution are currently unavailable under **AWS Marketplace** or **Community AMIs**. -7. On the **Choose an Instance Type** page, select the instance type as per the requirement of your use case and then click **Review and Launch** to launch the instance with default configurations.
+5. On the **Choose an Instance Type** page, select the instance type as per the requirement of your use case and then click **Review and Launch** to launch the instance with default configurations.
!!! Note * You can also continue customizing your instance before you launch the instance. Refer to the AWS documentation for more information. - * When configuring the security groups, ensure that you open at least ports 22 (for SSH access to the EC2 instance) and 5050 (for access to Snappy UI). + * On **Configure Security Group** page, ensure that you open at least ports 22 (for SSH access to the EC2 instance) and 5050 (to access SnappyData Monitoring Console) for public IP address of your laptop or client terminal. -8. You are directed to the last step **Review Instance Launch**. Check the details of your instance, and click **Launch**. + * If you need to connect to the SnappyData cluster via a JDBC client application or tool, open ports 1527 and 1528 for the public IP of the host where your application/tool is running, in the security group. -9. In the **Select an existing key pair or create a new key pair** dialog box, select a key pair. +6. You are directed to the last step **Review Instance Launch**. Check the details of your instance, and click **Launch**. -10. Click **Launch**. The Launch Status page is displayed. +7. In the **Select an existing key pair or create a new key pair** dialog box, select your key pair. -11. Click **View Instances**. The dashboard which lists the instances is displayed. +8. Click **Launch**. The Launch Status page is displayed. -12. Click **Refresh** to view the updated list and the status of the instance creation. +9. Click **View Instances**. The dashboard which lists the EC2 instances is displayed. -13. Once the status of the instance changes to **running**, you have successfully created and launched the instance with the SnappyData AMI. +10. Click **Refresh** to view the updated list and the status of the instance you just created. -14. Use SSH to connect to the instance using the **Ubuntu** username. You require: +11. Once the status of the instance changes to **running**, connect to the instance via SSH. You require: - * The private key file of the key pair with which the instance was launched, and + * The private key (.pem) file of the key pair with which the instance was launched, + + * The public DNS or IP address of the instance, and + + * The username to connect with. It depends on the AMI you selected above. For example, it could be **ec2-user** for Amazon Linux AMIs or **ubuntu** for Ubuntu-based AMIs. - * Details of the public hostname or IP address of the instance. Refer to the following documentation, for more information on [accessing an EC2 instance](http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/AccessingInstancesLinux.html). !!! Note - * The public hostname/IP address information is available on the EC2 dashboard > **Description** tab. - - * The SnappyData product distribution is already downloaded and extracted in the **/opt/snappydata** directory and Java 8 is installed. + * The public DNS/IP of the instance is available on the EC2 dashboard > **Instances** page. Select your EC2 instance and look for it in the lower half of the page. -15. If you had selected a SnappyData AMI in step 6 above, jump to step 20. +12. Download the required SnappyData distribution (.tar.gz) into this EC2 instance. You can find the latest SnappyData Community Edition (OSS) release [here](https://github.com/snappydatainc/snappydata/releases/latest). -16. Make Sure Java 8 is installed and set as default. For Amazon Linux 2018.03, you may need to uninstall Java 7 first. Below commands update OpenJDK to 8. + * When we make the SnappyData AMI available on AWS in future, it will have the distribution pre-installed. In that case, you can jump to [step 15](#15step). - sudo yum -y -q remove jre-1.7.0-openjdk - sudo yum -y -q install java-1.8.0-openjdk-devel - java -version # Ensure it prints correct Java version - -17. After you download the required SnappyData tarball distribution into this instance, extract it to /opt/snappydata/. +13. Extract the tarball to /opt/snappydata/. tar -xvf snappydata--bin.tar.gz sudo mv snappydata--bin /opt/snappydata chown -R ec2-user:ec2-user /opt/snappydata -18. Setup [passwordless ssh](../reference/misc/passwordless_ssh.md) on this instance. This requirement may be removed in future, for single-instance installation on AWS. +14. Make Sure Java 8 is installed and set as default. For Amazon Linux 2018.03, you may need to uninstall Java 7 first. Below commands update OpenJDK to 8. -19. Run below commands to configure the cluster on AWS. + sudo yum -y -q remove jre-1.7.0-openjdk + sudo yum -y -q install java-1.8.0-openjdk-devel + java -version # Ensure it prints correct Java version + +15. Setup [passwordless ssh](../reference/misc/passwordless_ssh.md) on this instance. This requirement may be removed in future, for single-instance installation on AWS. + +16. Run below commands to update the cluster configuration. curl http://169.254.169.254/latest/meta-data/local-ipv4 > /opt/snappydata/conf/locators curl http://169.254.169.254/latest/meta-data/local-ipv4 > /opt/snappydata/conf/servers curl http://169.254.169.254/latest/meta-data/local-ipv4 > /opt/snappydata/conf/leads -20. Go to the **/opt/snappydata** directory. Run the following command to start a basic cluster with one data node, one lead, and one locator. +17. Go to the **/opt/snappydata** directory. Run the following command to start a basic cluster with one data node, one lead, and one locator. ./sbin/snappy-start-all.sh -21. Make sure the security group associated with the ec2 instances have ports 1527-1528 accessible for the public IP of the ec2 instances before proceeding further. + +### Accessing SnappyData Cluster + +The quickest way to connect to your SnappyData cluster is probably using the snappy shell utility packaged with the distribution. + +You can launch the snappy shell either from the same EC2 instance or from your laptop where you have SnappyData installed. + +1. Connecting to the cluster from the same EC2 instance: + + * Launch the snappy shell. + + ./bin/snappy + + * **Important** Before connecting to the cluster, make sure the security group attached to this EC2 instance has ports 1527-1528 open for the public IP of the same ec2 instance. + + * Now, connect to the cluster using its private IP (you can also use the public DNS/IP instead): + + snappy> connect client '(private-ip-of-EC2-instance):1527'; + +2. Connecting to the cluster from your laptop (or any host outside AWS VPC): -22. One way to connect to this cluster is using snappy shell. + * Launch the snappy shell: - ./bin/snappy - snappy> connect client '(local-ip-of-EC2-instance):1527'; + ${SNAPPY_HOME}/bin/snappy -23. To connect from outside the AWS, make sure the security group associated with the ec2 instances have ports 1527-1528 accessible to your laptop (i.e. machine with snappydata installed), before proceeding further. + * **Important** Before connecting to the cluster, make sure the security group attached to this EC2 instance has ports 1527-1528 open for the public IP of your laptop (i.e. the host with SnappyData installed). - ./bin/snappy - snappy> connect client ':1527'; + * Now, connect to the cluster using the public DNS/IP of its EC2 instance: + snappy> connect client ':1527'; diff --git a/docs/quickstart/getting_started_with_docker_image.md b/docs/quickstart/getting_started_with_docker_image.md index 751b824c01..6f7e57ae53 100644 --- a/docs/quickstart/getting_started_with_docker_image.md +++ b/docs/quickstart/getting_started_with_docker_image.md @@ -2,12 +2,20 @@ # Getting Started with Docker Image The following instructions outline how to build a Docker image if you have the binaries of SnappyData.
-SnappyData does not provide a Docker image. -Before building the Docker image, ensure that you have already installed and configured the Docker properly. Refer to [Docker documentation](http://docs.docker.com/installation/) for more details. +!!!Note + SnappyData does not provide a Docker image. You must build it explicitly. -## Verify that Docker is Installed
-In the command prompt run the command: +Before building the Docker image, ensure the following: + +* You have Docker installed, configured, and it runs successfully on your machine. Refer to the [Docker documentation](http://docs.docker.com/installation) for more information on installing Docker. +* The Docker containers have access to at least 4GB of RAM on your machine. + +!!!Note + To allow non-root users to run Docker commands, follow the instructions [here](https://docs.docker.com/install/linux/linux-postinstall) + +## Verifying Docker Installation
+In the command prompt, run the command: ```pre $ docker run hello-world @@ -15,37 +23,152 @@ $ docker run hello-world ``` -## Build your own Docker image of SnappyData
+## Building Docker Image of SnappyData
-A sample Dockerfile is provided which you can use to create your own Docker image of SnappyData. +You can use the Dockerfile that is provided and create your own Docker image of SnappyData. Download the [Dockerfile](https://github.com/SnappyDataInc/snappy-cloud-tools/blob/master/docker/Dockerfile) script and place it into a directory. The Dockerfile contains a link to the latest SnappyData OSS version to build the image. -Download the [Dockerfile](https://github.com/SnappyDataInc/snappy-cloud-tools/blob/master/docker/Dockerfile) and -[start](https://github.com/SnappyDataInc/snappy-cloud-tools/blob/master/docker/start) script and place them into a single directory. This Dockerfile uses the SnappyData 1.1.1 build. +Move into the directory containing the downloaded Dockerfile and then run the Docker build command with the required details to build the Docker image. You can create an image using any one of the following options: -Move to that directory and run the following commands with appropriate details: +* [Building Image from the Latest Version of SnappyData OSS](#builddockerimagesnappy) +* [Building Image from a URL Directing to SnappyData Binaries](#builddockerurl) +* [Building Image from Local Copy of SnappyData Product TAR file](#builddockerimageslocal) - $ docker build -t /snappydata: -f Dockerfile . - $ docker push /snappydata: - For example: + +### Building Image from the Latest Version of SnappyData OSS - $ docker build -t snappydatainc/snappydata:1.1.1 -f Dockerfile . - $ docker push snappydatainc/snappydata:1.1.1 +By default, the Dockerfile creates a Docker image from the latest version of SnappyData OSS. +``` +$ docker build -t /[:] . +``` -## Launch SnappyData
-In the command prompt, type the following command to launch the SnappyData cluster in single container. -This fetches the Docker image from your Docker registry, if the image is not available locally, launches the cluster in a container and leads to the Spark shell. +!!!Note + If you do not provide any argument to the Dockerfile, the latest version of the SnappyData OSS release is downloaded and a Docker image for the same is built. -!!! Note - Ensure that the Docker containers have access to at least 4 GB of RAM on your machine. +For example: + +The following command builds an image with tag `latest`: + +``` +$ docker build -t myrepo/snappydata . +``` + +The following command builds an image with tag `1.1.1 `: + +``` +$ docker build -t myrepo/snappydata:1.1.1 . +``` + + +### Building Image from a URL Directing to SnappyData Binaries + +If you want to create a Docker image from any of the previous versions of SnappyData, you can specify the URL of the tarfile in the build command. + + +``` +$ docker build -t /[:] . --build-arg TARFILE_LOC= + +``` + +For example: + +``` +$ docker build -t myrepo/snappydata . --build-arg TARFILE_LOC=https://github.com/SnappyDataInc/snappydata/releases/download/v1.1.1/snappydata-1.1.1-bin.tar.gz +``` + + +### Building Image from Local Copy of SnappyData Product TAR file + +If you have already downloaded the SnappyData tarfile locally onto your machine, use the following steps to build an image from the downloaded binaries. To download SnappyData, refer to the [Provisioning SnappyData](https://snappydatainc.github.io/snappydata/install/) section in the product documentation. + +Copy the downloaded **tar.gz** file to the Docker folder where you have placed the Dockerfile and run the following command: + +``` +$ docker build -t /[:] . --build-arg TARFILE_LOC= + +``` + +For example: + +``` +$ docker build -t myrepo/snappydata . --build-arg TARFILE_LOC=snappydata-1.1.1-bin.tar.gz +``` + + +## Verifying Details of Docker Images + +After the Docker build is successful, you can check the details for Docker images using the `docker images` command. + +For example: + +``` +$ docker images + +``` + +## Publishing Docker Image + +If you want to publish the Docker image onto the Docker Hub, login to the Docker account using `docker login` command, and provide your credentials. For more information on Docker login, visit [here](https://docs.docker.com/engine/reference/commandline/login). After a successful login, you can publish the Docker image using the `docker push` command. + +``` +$ docker push /[:] +``` +Ensure to use the same name in the `docker push` that is used in `docker build`. + +For example: + +``` +$ docker push myrepo/snappydata +``` +!!!Note + This example only showcases how to push an image onto Docker Hub. You can also publish the image to other container registries such as [gcr.io](http://gcr.io). For publishing on gcr.io, you can refer [this document](https://cloud.google.com/container-registry/docs/pushing-and-pulling). + +## Launching SnappyData Container + +The command to launch SnappyData container is different for Linux and macOS. + +### Launching SnappyData Container on Linux + +In the command prompt, execute the following commands to launch the SnappyData cluster in a single container. + +``` +$ docker run -itd --net=host --name /[:] start all + +# -i: keep the STDIN open even if not attached. +# -t: Allocate pseudo-TTY. +# -d: Detach and run the container in background and print container ID. +# --net=host: Use the Docker host network stack. +``` + +If the image is not available locally, this fetches the Docker image from the Docker registry, launches a default cluster consisting of one data node, one lead, and one locator in a container. + + + +``` +$ docker run -itd --net=host --name snappydata myrepo/snappydata start all -```pre -$ docker run -it -p 5050:5050 /snappydata bin/spark-shell ``` -The latest Docker image file starts downloading to your local machine. Depending on your network connection, this may take some time.
+### Launching SnappyData Container on macOS + +If you are using macOS, you must redirect the ports manually using `-p` parameter. If you use `--net=host`, it may not work correctly on the macOS. You can use the following modified command for macOS: + +``` +$ docker run -d --name=snappydata -p 5050:5050 -p 1527:1527 -p 1528:1528 myrepo/snappydata start all -hostname-for-clients= +``` + +The `-hostname-for-clients` parameter sets the IP Address or Hostname that the server listens for client connections. The command may take few seconds to execute. + -After you have launched the Spark shell, in the `$ scala>` prompt, follow the steps explained [here](using_spark_scala_apis.md).
+## Commonly used Docker Commands -For more details about how you can work with the Docker image see [Snappy Cloud Tools](https://github.com/SnappyDataInc/snappy-cloud-tools/tree/master/docker). +| Description| Docker Commands | +|--------|--------| +| To check details of all the Docker containers. | `$ docker ps -a ` | +| To check the container logs. | `$ docker logs ` | +| To launch Snappy Shell. | `$ docker exec -it ./bin/snappy` | +| To launch Spark Shell. | `$ docker exec -it ./bin/spark-shell ` | +| To stop the cluster. | `$ docker exec -it ./sbin/snappy-stop-all.sh ` | +| To stop the container. | `$ docker stop ` | +| To open bash shell inside the container. | `$ docker exec -it /bin/bash` | \ No newline at end of file diff --git a/mkdocs.yml b/mkdocs.yml index d4f01901b2..914808522f 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -14,8 +14,8 @@ pages: - 'Provisioning SnappyData': - 'System Requirements': 'install/system_requirements.md' - 'Installing SnappyData On-Premise': 'install/install_on_premise.md' - - 'Setup SnappyData Cluster on AWS': 'install/setting_up_cluster_on_amazon_web_services.md' - - 'Setup SnappyData Cluster on Kubernetes': 'kubernetes.md' + - 'Setting-up SnappyData Cluster on AWS': 'install/setting_up_cluster_on_amazon_web_services.md' + - 'Setting-up SnappyData Cluster on Kubernetes': 'kubernetes.md' - 'Building a Docker Image with SnappyData Binaries': 'quickstart/getting_started_with_docker_image.md' - 'Building SnappyData from Source files': 'install/building_from_source.md' - 'Upgrading SnappyData': 'install/upgrade.md' @@ -23,7 +23,7 @@ pages: - 'Getting Started': - 'On-Premise': 'quickstart/getting_started_by_installing_snappydata_on-premise.md' - 'Kubernetes': 'quickstart/getting_started_on_kubernetes.md' - - 'Docker Image': 'quickstart/getting_started_with_docker_image.md' +# - 'Docker Image': 'quickstart/getting_started_with_docker_image.md' - 'Spark Distribution': 'quickstart/getting_started_with_your_spark_distribution.md' - 'SnappyData Quickstart Guide': 'quickstart/snappydataquick_start.md' - 'Using Spark Scala APIs': 'quickstart/using_spark_scala_apis.md' From 614fe9466de3e7c48b65ef15bec99be9f4276eb4 Mon Sep 17 00:00:00 2001 From: ahshahid Date: Tue, 26 Nov 2019 12:35:17 -0800 Subject: [PATCH 018/101] added some climate data for aqp tests --- .../common/src/main/resources/climatedata.csv | 5000 +++++++++++++++++ 1 file changed, 5000 insertions(+) create mode 100644 tests/common/src/main/resources/climatedata.csv diff --git a/tests/common/src/main/resources/climatedata.csv b/tests/common/src/main/resources/climatedata.csv new file mode 100644 index 0000000000..8ff7bb231e --- /dev/null +++ b/tests/common/src/main/resources/climatedata.csv @@ -0,0 +1,5000 @@ +ID,YMD,ELEMENT,DATA_VALUE,M_Flag,Q_Flag,S_Flag,OBS_TIME +EZE00100082,17880101,TMAX,30,,,E, +EZE00100082,17880101,TMIN,20,,,E, +ITE00100554,17880101,TMAX,75,,,E, +ITE00100554,17880101,TMIN,63,,,E, +EZE00100082,17880102,TMAX,36,,,E, +EZE00100082,17880102,TMIN,24,,,E, +ITE00100554,17880102,TMAX,73,,,E, +ITE00100554,17880102,TMIN,54,,,E, +EZE00100082,17880103,TMAX,46,,,E, +EZE00100082,17880103,TMIN,33,,,E, +ITE00100554,17880103,TMAX,66,,,E, +ITE00100554,17880103,TMIN,65,,,E, +EZE00100082,17880104,TMAX,80,,,E, +EZE00100082,17880104,TMIN,42,,,E, +ITE00100554,17880104,TMAX,63,,,E, +ITE00100554,17880104,TMIN,50,,,E, +EZE00100082,17880105,TMAX,88,,,E, +EZE00100082,17880105,TMIN,37,,,E, +ITE00100554,17880105,TMAX,65,,,E, +ITE00100554,17880105,TMIN,56,,,E, +EZE00100082,17880106,TMAX,78,,,E, +EZE00100082,17880106,TMIN,30,,,E, +ITE00100554,17880106,TMAX,63,,,E, +ITE00100554,17880106,TMIN,56,,,E, +EZE00100082,17880107,TMAX,47,,,E, +EZE00100082,17880107,TMIN,36,,,E, +ITE00100554,17880107,TMAX,63,,,E, +ITE00100554,17880107,TMIN,58,,,E, +EZE00100082,17880108,TMAX,63,,,E, +EZE00100082,17880108,TMIN,37,,,E, +ITE00100554,17880108,TMAX,75,,,E, +ITE00100554,17880108,TMIN,58,,,E, +EZE00100082,17880109,TMAX,50,,,E, +EZE00100082,17880109,TMIN,15,,,E, +ITE00100554,17880109,TMAX,100,,,E, +ITE00100554,17880109,TMIN,75,,,E, +EZE00100082,17880110,TMAX,30,,,E, +EZE00100082,17880110,TMIN,2,,,E, +ITE00100554,17880110,TMAX,96,,,E, +ITE00100554,17880110,TMIN,63,,,E, +EZE00100082,17880111,TMAX,18,,,E, +EZE00100082,17880111,TMIN,-3,,,E, +ITE00100554,17880111,TMAX,71,,,E, +ITE00100554,17880111,TMIN,25,,,E, +EZE00100082,17880112,TMAX,45,,,E, +EZE00100082,17880112,TMIN,5,,,E, +ITE00100554,17880112,TMAX,38,,,E, +ITE00100554,17880112,TMIN,16,,,E, +EZE00100082,17880113,TMAX,46,,,E, +EZE00100082,17880113,TMIN,20,,,E, +ITE00100554,17880113,TMAX,29,,,E, +ITE00100554,17880113,TMIN,16,,,E, +EZE00100082,17880114,TMAX,33,,,E, +EZE00100082,17880114,TMIN,0,,,E, +ITE00100554,17880114,TMAX,20,,,E, +ITE00100554,17880114,TMIN,3,,,E, +EZE00100082,17880115,TMAX,0,,,E, +EZE00100082,17880115,TMIN,-45,,,E, +ITE00100554,17880115,TMAX,41,,,E, +ITE00100554,17880115,TMIN,8,,,E, +EZE00100082,17880116,TMAX,42,,,E, +EZE00100082,17880116,TMIN,-56,,,E, +ITE00100554,17880116,TMAX,45,,,E, +ITE00100554,17880116,TMIN,0,,,E, +EZE00100082,17880117,TMAX,69,,,E, +EZE00100082,17880117,TMIN,42,,,E, +ITE00100554,17880117,TMAX,78,,,E, +ITE00100554,17880117,TMIN,0,,,E, +EZE00100082,17880118,TMAX,55,,,E, +EZE00100082,17880118,TMIN,18,,,E, +ITE00100554,17880118,TMAX,79,,,E, +ITE00100554,17880118,TMIN,16,,,E, +EZE00100082,17880119,TMAX,40,,,E, +EZE00100082,17880119,TMIN,10,,,E, +ITE00100554,17880119,TMAX,50,,,E, +ITE00100554,17880119,TMIN,29,,,E, +EZE00100082,17880120,TMAX,10,,,E, +EZE00100082,17880120,TMIN,-30,,,E, +ITE00100554,17880120,TMAX,46,,,E, +ITE00100554,17880120,TMIN,4,,,E, +EZE00100082,17880121,TMAX,-3,,,E, +EZE00100082,17880121,TMIN,-46,,,E, +ITE00100554,17880121,TMAX,20,,,E, +ITE00100554,17880121,TMIN,0,,,E, +EZE00100082,17880122,TMAX,18,,,E, +EZE00100082,17880122,TMIN,-36,,,E, +ITE00100554,17880122,TMAX,13,,,E, +ITE00100554,17880122,TMIN,-25,,,E, +EZE00100082,17880123,TMAX,33,,,E, +EZE00100082,17880123,TMIN,9,,,E, +ITE00100554,17880123,TMAX,38,,,E, +ITE00100554,17880123,TMIN,-25,,,E, +EZE00100082,17880124,TMAX,55,,,E, +EZE00100082,17880124,TMIN,28,,,E, +ITE00100554,17880124,TMAX,90,,,E, +ITE00100554,17880124,TMIN,20,,,E, +EZE00100082,17880125,TMAX,53,,,E, +EZE00100082,17880125,TMIN,45,,,E, +ITE00100554,17880125,TMAX,78,,,E, +ITE00100554,17880125,TMIN,3,,,E, +EZE00100082,17880126,TMAX,50,,,E, +EZE00100082,17880126,TMIN,17,,,E, +ITE00100554,17880126,TMAX,54,,,E, +ITE00100554,17880126,TMIN,4,,,E, +EZE00100082,17880127,TMAX,35,,,E, +EZE00100082,17880127,TMIN,11,,,E, +ITE00100554,17880127,TMAX,63,,,E, +ITE00100554,17880127,TMIN,29,,,E, +EZE00100082,17880128,TMAX,8,,,E, +EZE00100082,17880128,TMIN,-16,,,E, +ITE00100554,17880128,TMAX,63,,,E, +ITE00100554,17880128,TMIN,28,,,E, +EZE00100082,17880129,TMAX,14,,,E, +EZE00100082,17880129,TMIN,-9,,,E, +ITE00100554,17880129,TMAX,45,,,E, +ITE00100554,17880129,TMIN,0,,,E, +EZE00100082,17880130,TMAX,-9,,,E, +EZE00100082,17880130,TMIN,-21,,,E, +ITE00100554,17880130,TMAX,33,,,E, +ITE00100554,17880130,TMIN,8,,,E, +EZE00100082,17880131,TMAX,-18,,,E, +EZE00100082,17880131,TMIN,-40,,,E, +ITE00100554,17880131,TMAX,20,,,E, +ITE00100554,17880131,TMIN,0,,,E, +EZE00100082,17880201,TMAX,-20,,,E, +EZE00100082,17880201,TMIN,-55,,,E, +ITE00100554,17880201,TMAX,20,,,E, +ITE00100554,17880201,TMIN,-15,,,E, +EZE00100082,17880202,TMAX,12,,,E, +EZE00100082,17880202,TMIN,-33,,,E, +ITE00100554,17880202,TMAX,21,,,E, +ITE00100554,17880202,TMIN,4,,,E, +EZE00100082,17880203,TMAX,32,,,E, +EZE00100082,17880203,TMIN,-9,,,E, +ITE00100554,17880203,TMAX,25,,,E, +ITE00100554,17880203,TMIN,3,,,E, +EZE00100082,17880204,TMAX,37,,,E, +EZE00100082,17880204,TMIN,4,,,E, +ITE00100554,17880204,TMAX,34,,,E, +ITE00100554,17880204,TMIN,13,,,E, +EZE00100082,17880205,TMAX,31,,,E, +EZE00100082,17880205,TMIN,0,,,E, +ITE00100554,17880205,TMAX,50,,,E, +ITE00100554,17880205,TMIN,25,,,E, +EZE00100082,17880206,TMAX,75,,,E, +EZE00100082,17880206,TMIN,15,,,E, +ITE00100554,17880206,TMAX,79,,,E, +ITE00100554,17880206,TMIN,41,,,E, +EZE00100082,17880207,TMAX,71,,,E, +EZE00100082,17880207,TMIN,18,,,E, +ITE00100554,17880207,TMAX,59,,,E, +ITE00100554,17880207,TMIN,50,,,E, +EZE00100082,17880208,TMAX,23,,,E, +EZE00100082,17880208,TMIN,-15,,,E, +ITE00100554,17880208,TMAX,59,,,E, +ITE00100554,17880208,TMIN,46,,,E, +EZE00100082,17880209,TMAX,16,,,E, +EZE00100082,17880209,TMIN,-42,,,E, +ITE00100554,17880209,TMAX,63,,,E, +ITE00100554,17880209,TMIN,50,,,E, +EZE00100082,17880210,TMAX,26,,,E, +EZE00100082,17880210,TMIN,-17,,,E, +ITE00100554,17880210,TMAX,58,,,E, +ITE00100554,17880210,TMIN,41,,,E, +EZE00100082,17880211,TMAX,36,,,E, +EZE00100082,17880211,TMIN,-33,,,E, +ITE00100554,17880211,TMAX,59,,,E, +ITE00100554,17880211,TMIN,25,,,E, +EZE00100082,17880212,TMAX,6,,,E, +EZE00100082,17880212,TMIN,-54,,,E, +ITE00100554,17880212,TMAX,46,,,E, +ITE00100554,17880212,TMIN,13,,,E, +EZE00100082,17880213,TMAX,2,,,E, +EZE00100082,17880213,TMIN,-37,,,E, +ITE00100554,17880213,TMAX,46,,,E, +ITE00100554,17880213,TMIN,3,,,E, +EZE00100082,17880214,TMAX,12,,,E, +EZE00100082,17880214,TMIN,-47,,,E, +ITE00100554,17880214,TMAX,63,,,E, +ITE00100554,17880214,TMIN,13,,,E, +EZE00100082,17880215,TMAX,-38,,,E, +EZE00100082,17880215,TMIN,-62,,,E, +ITE00100554,17880215,TMAX,90,,,E, +ITE00100554,17880215,TMIN,13,,,E, +EZE00100082,17880216,TMAX,-23,,,E, +EZE00100082,17880216,TMIN,-71,,,E, +ITE00100554,17880216,TMAX,100,,,E, +ITE00100554,17880216,TMIN,13,,,E, +EZE00100082,17880217,TMAX,-21,,,E, +EZE00100082,17880217,TMIN,-53,,,E, +ITE00100554,17880217,TMAX,100,,,E, +ITE00100554,17880217,TMIN,45,,,E, +EZE00100082,17880218,TMAX,-53,,,E, +EZE00100082,17880218,TMIN,-75,,,E, +ITE00100554,17880218,TMAX,113,,,E, +ITE00100554,17880218,TMIN,25,,,E, +EZE00100082,17880219,TMAX,-40,,,E, +EZE00100082,17880219,TMIN,-86,,,E, +ITE00100554,17880219,TMAX,58,,,E, +ITE00100554,17880219,TMIN,29,,,E, +EZE00100082,17880220,TMAX,0,,,E, +EZE00100082,17880220,TMIN,-79,,,E, +ITE00100554,17880220,TMAX,44,,,E, +ITE00100554,17880220,TMIN,35,,,E, +EZE00100082,17880221,TMAX,47,,,E, +EZE00100082,17880221,TMIN,-21,,,E, +ITE00100554,17880221,TMAX,41,,,E, +ITE00100554,17880221,TMIN,40,,,E, +EZE00100082,17880222,TMAX,77,,,E, +EZE00100082,17880222,TMIN,23,,,E, +ITE00100554,17880222,TMAX,59,,,E, +ITE00100554,17880222,TMIN,25,,,E, +EZE00100082,17880223,TMAX,90,,,E, +EZE00100082,17880223,TMIN,15,,,E, +ITE00100554,17880223,TMAX,75,,,E, +ITE00100554,17880223,TMIN,25,,,E, +EZE00100082,17880224,TMAX,105,,,E, +EZE00100082,17880224,TMIN,61,,,E, +ITE00100554,17880224,TMAX,50,,,E, +ITE00100554,17880224,TMIN,50,,,E, +EZE00100082,17880225,TMAX,67,,,E, +EZE00100082,17880225,TMIN,45,,,E, +ITE00100554,17880225,TMAX,113,,,E, +ITE00100554,17880225,TMIN,53,,,E, +EZE00100082,17880226,TMAX,46,,,E, +EZE00100082,17880226,TMIN,28,,,E, +ITE00100554,17880226,TMAX,113,,,E, +ITE00100554,17880226,TMIN,41,,,E, +EZE00100082,17880227,TMAX,83,,,E, +EZE00100082,17880227,TMIN,22,,,E, +ITE00100554,17880227,TMAX,83,,,E, +ITE00100554,17880227,TMIN,71,,,E, +EZE00100082,17880228,TMAX,114,,,E, +EZE00100082,17880229,TMAX,97,,,E, +EZE00100082,17880228,TMIN,60,,,E, +EZE00100082,17880229,TMIN,49,,,E, +ITE00100554,17880228,TMAX,108,,,E, +ITE00100554,17880229,TMAX,113,,,E, +ITE00100554,17880228,TMIN,75,,,E, +ITE00100554,17880229,TMIN,75,,,E, +EZE00100082,17880301,TMAX,82,,,E, +EZE00100082,17880301,TMIN,38,,,E, +ITE00100554,17880301,TMAX,100,,,E, +ITE00100554,17880301,TMIN,96,,,E, +EZE00100082,17880302,TMAX,92,,,E, +EZE00100082,17880302,TMIN,53,,,E, +ITE00100554,17880302,TMAX,100,,,E, +ITE00100554,17880302,TMIN,79,,,E, +EZE00100082,17880303,TMAX,53,,,E, +EZE00100082,17880303,TMIN,-14,,,E, +ITE00100554,17880303,TMAX,113,,,E, +ITE00100554,17880303,TMIN,38,,,E, +EZE00100082,17880304,TMAX,30,,,E, +EZE00100082,17880304,TMIN,-33,,,E, +ITE00100554,17880304,TMAX,113,,,E, +ITE00100554,17880304,TMIN,50,,,E, +EZE00100082,17880305,TMAX,15,,,E, +EZE00100082,17880305,TMIN,-15,,,E, +ITE00100554,17880305,TMAX,100,,,E, +ITE00100554,17880305,TMIN,46,,,E, +EZE00100082,17880306,TMAX,53,,,E, +EZE00100082,17880306,TMIN,-23,,,E, +ITE00100554,17880306,TMAX,75,,,E, +ITE00100554,17880306,TMIN,50,,,E, +EZE00100082,17880307,TMAX,46,,,E, +EZE00100082,17880307,TMIN,-14,,,E, +ITE00100554,17880307,TMAX,113,,,E, +ITE00100554,17880307,TMIN,33,,,E, +EZE00100082,17880308,TMAX,45,,,E, +EZE00100082,17880308,TMIN,3,,,E, +ITE00100554,17880308,TMAX,113,,,E, +ITE00100554,17880308,TMIN,63,,,E, +EZE00100082,17880309,TMAX,94,,,E, +EZE00100082,17880309,TMIN,14,,,E, +ITE00100554,17880309,TMAX,128,,,E, +ITE00100554,17880309,TMIN,79,,,E, +EZE00100082,17880310,TMAX,28,,,E, +EZE00100082,17880310,TMIN,3,,,E, +ITE00100554,17880310,TMAX,128,,,E, +ITE00100554,17880310,TMIN,58,,,E, +EZE00100082,17880311,TMAX,12,,,E, +EZE00100082,17880311,TMIN,-12,,,E, +ITE00100554,17880311,TMAX,128,,,E, +ITE00100554,17880311,TMIN,90,,,E, +EZE00100082,17880312,TMAX,25,,,E, +EZE00100082,17880312,TMIN,-8,,,E, +ITE00100554,17880312,TMAX,140,,,E, +ITE00100554,17880312,TMIN,81,,,E, +EZE00100082,17880313,TMAX,30,,,E, +EZE00100082,17880313,TMIN,-4,,,E, +ITE00100554,17880313,TMAX,145,,,E, +ITE00100554,17880313,TMIN,65,,,E, +EZE00100082,17880314,TMAX,36,,,E, +EZE00100082,17880314,TMIN,-16,,,E, +ITE00100554,17880314,TMAX,134,,,E, +ITE00100554,17880314,TMIN,88,,,E, +EZE00100082,17880315,TMAX,16,,,E, +EZE00100082,17880315,TMIN,-6,,,E, +ITE00100554,17880315,TMAX,125,,,E, +ITE00100554,17880315,TMIN,103,,,E, +EZE00100082,17880316,TMAX,11,,,E, +EZE00100082,17880316,TMIN,-23,,,E, +ITE00100554,17880316,TMAX,146,,,E, +ITE00100554,17880316,TMIN,96,,,E, +EZE00100082,17880317,TMAX,17,,,E, +EZE00100082,17880317,TMIN,-16,,,E, +ITE00100554,17880317,TMAX,144,,,E, +ITE00100554,17880317,TMIN,103,,,E, +EZE00100082,17880318,TMAX,48,,,E, +EZE00100082,17880318,TMIN,-3,,,E, +ITE00100554,17880318,TMAX,128,,,E, +ITE00100554,17880318,TMIN,103,,,E, +EZE00100082,17880319,TMAX,65,,,E, +EZE00100082,17880319,TMIN,28,,,E, +ITE00100554,17880319,TMAX,153,,,E, +ITE00100554,17880319,TMIN,78,,,E, +EZE00100082,17880320,TMAX,28,,,E, +EZE00100082,17880320,TMIN,6,,,E, +ITE00100554,17880320,TMAX,159,,,E, +ITE00100554,17880320,TMIN,90,,,E, +EZE00100082,17880321,TMAX,60,,,E, +EZE00100082,17880321,TMIN,14,,,E, +ITE00100554,17880321,TMAX,165,,,E, +ITE00100554,17880321,TMIN,90,,,E, +EZE00100082,17880322,TMAX,102,,,E, +EZE00100082,17880322,TMIN,12,,,E, +ITE00100554,17880322,TMAX,128,,,E, +ITE00100554,17880322,TMIN,106,,,E, +EZE00100082,17880323,TMAX,90,,,E, +EZE00100082,17880323,TMIN,33,,,E, +ITE00100554,17880323,TMAX,138,,,E, +ITE00100554,17880323,TMIN,123,,,E, +EZE00100082,17880324,TMAX,104,,,E, +EZE00100082,17880324,TMIN,39,,,E, +ITE00100554,17880324,TMAX,150,,,E, +ITE00100554,17880324,TMIN,113,,,E, +EZE00100082,17880325,TMAX,107,,,E, +EZE00100082,17880325,TMIN,23,,,E, +ITE00100554,17880325,TMAX,134,,,E, +ITE00100554,17880325,TMIN,103,,,E, +EZE00100082,17880326,TMAX,127,,,E, +EZE00100082,17880326,TMIN,27,,,E, +ITE00100554,17880326,TMAX,134,,,E, +ITE00100554,17880326,TMIN,116,,,E, +EZE00100082,17880327,TMAX,114,,,E, +EZE00100082,17880327,TMIN,41,,,E, +ITE00100554,17880327,TMAX,131,,,E, +ITE00100554,17880327,TMIN,108,,,E, +EZE00100082,17880328,TMAX,125,,,E, +EZE00100082,17880328,TMIN,68,,,E, +ITE00100554,17880328,TMAX,138,,,E, +ITE00100554,17880328,TMIN,104,,,E, +EZE00100082,17880329,TMAX,137,,,E, +EZE00100082,17880329,TMIN,75,,,E, +ITE00100554,17880329,TMAX,156,,,E, +ITE00100554,17880329,TMIN,103,,,E, +EZE00100082,17880330,TMAX,155,,,E, +EZE00100082,17880330,TMIN,52,,,E, +ITE00100554,17880330,TMAX,163,,,E, +ITE00100554,17880330,TMIN,113,,,E, +EZE00100082,17880331,TMAX,160,,,E, +EZE00100082,17880331,TMIN,68,,,E, +ITE00100554,17880331,TMAX,163,,,E, +ITE00100554,17880331,TMIN,94,,,E, +EZE00100082,17880401,TMAX,142,,,E, +EZE00100082,17880401,TMIN,94,,,E, +ITE00100554,17880401,TMAX,179,,,E, +ITE00100554,17880401,TMIN,96,,,E, +EZE00100082,17880402,TMAX,107,,,E, +EZE00100082,17880402,TMIN,76,,,E, +ITE00100554,17880402,TMAX,163,,,E, +ITE00100554,17880402,TMIN,109,,,E, +EZE00100082,17880403,TMAX,134,,,E, +EZE00100082,17880403,TMIN,72,,,E, +ITE00100554,17880403,TMAX,188,,,E, +ITE00100554,17880403,TMIN,88,,,E, +EZE00100082,17880404,TMAX,120,,,E, +EZE00100082,17880404,TMIN,50,,,E, +ITE00100554,17880404,TMAX,150,,,E, +ITE00100554,17880404,TMIN,103,,,E, +EZE00100082,17880405,TMAX,93,,,E, +EZE00100082,17880405,TMIN,28,,,E, +ITE00100554,17880405,TMAX,100,,,E, +ITE00100554,17880405,TMIN,75,,,E, +EZE00100082,17880406,TMAX,76,,,E, +EZE00100082,17880406,TMIN,33,,,E, +ITE00100554,17880406,TMAX,116,,,E, +ITE00100554,17880406,TMIN,50,,,E, +EZE00100082,17880407,TMAX,88,,,E, +EZE00100082,17880407,TMIN,40,,,E, +ITE00100554,17880407,TMAX,129,,,E, +ITE00100554,17880407,TMIN,38,,,E, +EZE00100082,17880408,TMAX,84,,,E, +EZE00100082,17880408,TMIN,44,,,E, +ITE00100554,17880408,TMAX,154,,,E, +ITE00100554,17880408,TMIN,65,,,E, +EZE00100082,17880409,TMAX,133,,,E, +EZE00100082,17880409,TMIN,75,,,E, +ITE00100554,17880409,TMAX,158,,,E, +ITE00100554,17880409,TMIN,90,,,E, +EZE00100082,17880410,TMAX,133,,,E, +EZE00100082,17880410,TMIN,69,,,E, +ITE00100554,17880410,TMAX,166,,,E, +ITE00100554,17880410,TMIN,90,,,E, +EZE00100082,17880411,TMAX,174,,,E, +EZE00100082,17880411,TMIN,60,,,E, +ITE00100554,17880411,TMAX,178,,,E, +ITE00100554,17880411,TMIN,100,,,E, +EZE00100082,17880412,TMAX,173,,,E, +EZE00100082,17880412,TMIN,80,,,E, +ITE00100554,17880412,TMAX,188,,,E, +ITE00100554,17880412,TMIN,110,,,E, +EZE00100082,17880413,TMAX,133,,,E, +EZE00100082,17880413,TMIN,76,,,E, +ITE00100554,17880413,TMAX,200,,,E, +ITE00100554,17880413,TMIN,113,,,E, +EZE00100082,17880414,TMAX,141,,,E, +EZE00100082,17880414,TMIN,49,,,E, +ITE00100554,17880414,TMAX,200,,,E, +ITE00100554,17880414,TMIN,116,,,E, +EZE00100082,17880415,TMAX,140,,,E, +EZE00100082,17880415,TMIN,62,,,E, +ITE00100554,17880415,TMAX,190,,,E, +ITE00100554,17880415,TMIN,115,,,E, +EZE00100082,17880416,TMAX,62,,,E, +EZE00100082,17880416,TMIN,32,,,E, +ITE00100554,17880416,TMAX,200,,,E, +ITE00100554,17880416,TMIN,100,,,E, +EZE00100082,17880417,TMAX,88,,,E, +EZE00100082,17880417,TMIN,26,,,E, +ITE00100554,17880417,TMAX,181,,,E, +ITE00100554,17880417,TMIN,119,,,E, +EZE00100082,17880418,TMAX,135,,,E, +EZE00100082,17880418,TMIN,61,,,E, +ITE00100554,17880418,TMAX,156,,,E, +ITE00100554,17880418,TMIN,116,,,E, +EZE00100082,17880419,TMAX,167,,,E, +EZE00100082,17880419,TMIN,77,,,E, +ITE00100554,17880419,TMAX,188,,,E, +ITE00100554,17880419,TMIN,113,,,E, +EZE00100082,17880420,TMAX,164,,,E, +EZE00100082,17880420,TMIN,109,,,E, +ITE00100554,17880420,TMAX,213,,,E, +ITE00100554,17880420,TMIN,119,,,E, +EZE00100082,17880421,TMAX,180,,,E, +EZE00100082,17880421,TMIN,92,,,E, +ITE00100554,17880421,TMAX,221,,,E, +ITE00100554,17880421,TMIN,133,,,E, +EZE00100082,17880422,TMAX,194,,,E, +EZE00100082,17880422,TMIN,111,,,E, +ITE00100554,17880422,TMAX,228,,,E, +ITE00100554,17880422,TMIN,146,,I,E, +EZE00100082,17880423,TMAX,145,,,E, +EZE00100082,17880423,TMIN,93,,,E, +ITE00100554,17880423,TMAX,113,,I,E, +ITE00100554,17880423,TMIN,100,,,E, +EZE00100082,17880424,TMAX,165,,,E, +EZE00100082,17880424,TMIN,74,,,E, +ITE00100554,17880424,TMAX,175,,,E, +ITE00100554,17880424,TMIN,86,,,E, +EZE00100082,17880425,TMAX,156,,,E, +EZE00100082,17880425,TMIN,80,,,E, +ITE00100554,17880425,TMAX,200,,,E, +ITE00100554,17880425,TMIN,104,,,E, +EZE00100082,17880426,TMAX,136,,,E, +EZE00100082,17880426,TMIN,77,,,E, +ITE00100554,17880426,TMAX,213,,,E, +ITE00100554,17880426,TMIN,124,,,E, +EZE00100082,17880427,TMAX,125,,,E, +EZE00100082,17880427,TMIN,74,,,E, +ITE00100554,17880427,TMAX,204,,,E, +ITE00100554,17880427,TMIN,119,,,E, +EZE00100082,17880428,TMAX,143,,,E, +EZE00100082,17880428,TMIN,86,,,E, +ITE00100554,17880428,TMAX,215,,,E, +ITE00100554,17880428,TMIN,141,,,E, +EZE00100082,17880429,TMAX,185,,,E, +EZE00100082,17880429,TMIN,89,,,E, +ITE00100554,17880429,TMAX,203,,,E, +ITE00100554,17880429,TMIN,150,,,E, +EZE00100082,17880430,TMAX,230,,,E, +EZE00100082,17880430,TMIN,86,,,E, +ITE00100554,17880430,TMAX,203,,,E, +ITE00100554,17880430,TMIN,150,,,E, +EZE00100082,17880501,TMAX,188,,,E, +EZE00100082,17880501,TMIN,91,,,E, +ITE00100554,17880501,TMAX,213,,,E, +ITE00100554,17880501,TMIN,154,,,E, +EZE00100082,17880502,TMAX,197,,,E, +EZE00100082,17880502,TMIN,97,,,E, +ITE00100554,17880502,TMAX,206,,,E, +ITE00100554,17880502,TMIN,156,,,E, +EZE00100082,17880503,TMAX,217,,,E, +EZE00100082,17880503,TMIN,99,,,E, +ITE00100554,17880503,TMAX,213,,,E, +ITE00100554,17880503,TMIN,131,,,E, +EZE00100082,17880504,TMAX,138,,,E, +EZE00100082,17880504,TMIN,74,,,E, +ITE00100554,17880504,TMAX,228,,,E, +ITE00100554,17880504,TMIN,150,,,E, +EZE00100082,17880505,TMAX,120,,,E, +EZE00100082,17880505,TMIN,36,,,E, +ITE00100554,17880505,TMAX,213,,,E, +ITE00100554,17880505,TMIN,140,,,E, +EZE00100082,17880506,TMAX,168,,,E, +EZE00100082,17880506,TMIN,52,,,E, +ITE00100554,17880506,TMAX,213,,,E, +ITE00100554,17880506,TMIN,146,,,E, +EZE00100082,17880507,TMAX,207,,,E, +EZE00100082,17880507,TMIN,62,,,E, +ITE00100554,17880507,TMAX,219,,,E, +ITE00100554,17880507,TMIN,156,,,E, +EZE00100082,17880508,TMAX,192,,,E, +EZE00100082,17880508,TMIN,136,,,E, +ITE00100554,17880508,TMAX,231,,,E, +ITE00100554,17880508,TMIN,169,,,E, +EZE00100082,17880509,TMAX,202,,,E, +EZE00100082,17880509,TMIN,128,,,E, +ITE00100554,17880509,TMAX,231,,,E, +ITE00100554,17880509,TMIN,175,,,E, +EZE00100082,17880510,TMAX,182,,,E, +EZE00100082,17880510,TMIN,119,,,E, +ITE00100554,17880510,TMAX,231,,,E, +ITE00100554,17880510,TMIN,169,,,E, +EZE00100082,17880511,TMAX,125,,,E, +EZE00100082,17880511,TMIN,85,,,E, +ITE00100554,17880511,TMAX,250,,,E, +ITE00100554,17880511,TMIN,169,,,E, +EZE00100082,17880512,TMAX,92,,,E, +EZE00100082,17880512,TMIN,74,,,E, +ITE00100554,17880512,TMAX,254,,,E, +ITE00100554,17880512,TMIN,165,,,E, +EZE00100082,17880513,TMAX,110,,,E, +EZE00100082,17880513,TMIN,63,,,E, +ITE00100554,17880513,TMAX,203,,,E, +ITE00100554,17880513,TMIN,178,,I,E, +EZE00100082,17880514,TMAX,115,,,E, +EZE00100082,17880514,TMIN,55,,,E, +ITE00100554,17880514,TMAX,153,,I,E, +ITE00100554,17880514,TMIN,125,,,E, +EZE00100082,17880515,TMAX,135,,,E, +EZE00100082,17880515,TMIN,80,,,E, +ITE00100554,17880515,TMAX,150,,,E, +ITE00100554,17880515,TMIN,103,,,E, +EZE00100082,17880516,TMAX,187,,,E, +EZE00100082,17880516,TMIN,79,,,E, +ITE00100554,17880516,TMAX,153,,,E, +ITE00100554,17880516,TMIN,128,,,E, +EZE00100082,17880517,TMAX,205,,,E, +EZE00100082,17880517,TMIN,100,,,E, +ITE00100554,17880517,TMAX,188,,,E, +ITE00100554,17880517,TMIN,128,,,E, +EZE00100082,17880518,TMAX,224,,,E, +EZE00100082,17880518,TMIN,120,,,E, +ITE00100554,17880518,TMAX,238,,,E, +ITE00100554,17880518,TMIN,153,,,E, +EZE00100082,17880519,TMAX,213,,,E, +EZE00100082,17880519,TMIN,130,,,E, +ITE00100554,17880519,TMAX,175,,,E, +ITE00100554,17880519,TMIN,140,,,E, +EZE00100082,17880520,TMAX,175,,,E, +EZE00100082,17880520,TMIN,111,,,E, +ITE00100554,17880520,TMAX,204,,,E, +ITE00100554,17880520,TMIN,138,,,E, +EZE00100082,17880521,TMAX,191,,,E, +EZE00100082,17880521,TMIN,84,,,E, +ITE00100554,17880521,TMAX,215,,,E, +ITE00100554,17880521,TMIN,153,,,E, +EZE00100082,17880522,TMAX,184,,,E, +EZE00100082,17880522,TMIN,107,,,E, +ITE00100554,17880522,TMAX,215,,,E, +ITE00100554,17880522,TMIN,153,,,E, +EZE00100082,17880523,TMAX,236,,,E, +EZE00100082,17880523,TMIN,114,,,E, +ITE00100554,17880523,TMAX,230,,,E, +ITE00100554,17880523,TMIN,155,,,E, +EZE00100082,17880524,TMAX,253,,,E, +EZE00100082,17880524,TMIN,160,,,E, +ITE00100554,17880524,TMAX,237,,,E, +ITE00100554,17880524,TMIN,155,,,E, +EZE00100082,17880525,TMAX,276,,,E, +EZE00100082,17880525,TMIN,154,,,E, +ITE00100554,17880525,TMAX,239,,,E, +ITE00100554,17880525,TMIN,177,,,E, +EZE00100082,17880526,TMAX,286,,,E, +EZE00100082,17880526,TMIN,153,,,E, +ITE00100554,17880526,TMAX,250,,,E, +ITE00100554,17880526,TMIN,198,,,E, +EZE00100082,17880527,TMAX,281,,,E, +EZE00100082,17880527,TMIN,168,,,E, +ITE00100554,17880527,TMAX,250,,,E, +ITE00100554,17880527,TMIN,200,,,E, +EZE00100082,17880528,TMAX,296,,,E, +EZE00100082,17880528,TMIN,170,,,E, +ITE00100554,17880528,TMAX,263,,,E, +ITE00100554,17880528,TMIN,219,,,E, +EZE00100082,17880529,TMAX,284,,,E, +EZE00100082,17880529,TMIN,177,,,E, +ITE00100554,17880529,TMAX,263,,,E, +ITE00100554,17880529,TMIN,215,,,E, +EZE00100082,17880530,TMAX,252,,,E, +EZE00100082,17880530,TMIN,178,,,E, +ITE00100554,17880530,TMAX,244,,,E, +ITE00100554,17880530,TMIN,215,,,E, +EZE00100082,17880531,TMAX,243,,,E, +EZE00100082,17880531,TMIN,170,,,E, +ITE00100554,17880531,TMAX,225,,,E, +ITE00100554,17880531,TMIN,215,,,E, +EZE00100082,17880601,TMAX,181,,,E, +EZE00100082,17880601,TMIN,129,,,E, +ITE00100554,17880601,TMAX,263,,,E, +ITE00100554,17880601,TMIN,200,,,E, +EZE00100082,17880602,TMAX,203,,,E, +EZE00100082,17880602,TMIN,119,,,E, +ITE00100554,17880602,TMAX,263,,,E, +ITE00100554,17880602,TMIN,209,,,E, +EZE00100082,17880603,TMAX,200,,,E, +EZE00100082,17880603,TMIN,122,,,E, +ITE00100554,17880603,TMAX,256,,,E, +ITE00100554,17880603,TMIN,200,,,E, +EZE00100082,17880604,TMAX,241,,,E, +EZE00100082,17880604,TMIN,107,,,E, +ITE00100554,17880604,TMAX,299,,,E, +ITE00100554,17880604,TMIN,211,,,E, +EZE00100082,17880605,TMAX,150,,,E, +EZE00100082,17880605,TMIN,105,,,E, +ITE00100554,17880605,TMAX,271,,,E, +ITE00100554,17880605,TMIN,221,,,E, +EZE00100082,17880606,TMAX,171,,,E, +EZE00100082,17880606,TMIN,103,,,E, +ITE00100554,17880606,TMAX,275,,,E, +ITE00100554,17880606,TMIN,213,,,E, +EZE00100082,17880607,TMAX,207,,,E, +EZE00100082,17880607,TMIN,137,,,E, +ITE00100554,17880607,TMAX,278,,,E, +ITE00100554,17880607,TMIN,221,,,E, +EZE00100082,17880608,TMAX,240,,,E, +EZE00100082,17880608,TMIN,125,,,E, +ITE00100554,17880608,TMAX,238,,,E, +ITE00100554,17880608,TMIN,215,,,E, +EZE00100082,17880609,TMAX,258,,,E, +EZE00100082,17880609,TMIN,161,,,E, +ITE00100554,17880609,TMAX,228,,,E, +ITE00100554,17880609,TMIN,194,,,E, +EZE00100082,17880610,TMAX,243,,,E, +EZE00100082,17880610,TMIN,154,,,E, +ITE00100554,17880610,TMAX,234,,,E, +ITE00100554,17880610,TMIN,190,,,E, +EZE00100082,17880611,TMAX,181,,,E, +EZE00100082,17880611,TMIN,143,,,E, +ITE00100554,17880611,TMAX,231,,,E, +ITE00100554,17880611,TMIN,206,,,E, +EZE00100082,17880612,TMAX,187,,,E, +EZE00100082,17880612,TMIN,147,,,E, +ITE00100554,17880612,TMAX,228,,,E, +ITE00100554,17880612,TMIN,221,,,E, +EZE00100082,17880613,TMAX,188,,,E, +EZE00100082,17880613,TMIN,134,,,E, +ITE00100554,17880613,TMAX,234,,,E, +ITE00100554,17880613,TMIN,203,,,E, +EZE00100082,17880614,TMAX,231,,,E, +EZE00100082,17880614,TMIN,138,,,E, +ITE00100554,17880614,TMAX,265,,,E, +ITE00100554,17880614,TMIN,215,,,E, +EZE00100082,17880615,TMAX,257,,,E, +EZE00100082,17880615,TMIN,158,,,E, +ITE00100554,17880615,TMAX,269,,,E, +ITE00100554,17880615,TMIN,209,,,E, +EZE00100082,17880616,TMAX,269,,,E, +EZE00100082,17880616,TMIN,162,,,E, +ITE00100554,17880616,TMAX,253,,,E, +ITE00100554,17880616,TMIN,206,,,E, +EZE00100082,17880617,TMAX,285,,,E, +EZE00100082,17880617,TMIN,172,,,E, +ITE00100554,17880617,TMAX,256,,,E, +ITE00100554,17880617,TMIN,219,,,E, +EZE00100082,17880618,TMAX,295,,,E, +EZE00100082,17880618,TMIN,205,,,E, +ITE00100554,17880618,TMAX,284,,,E, +ITE00100554,17880618,TMIN,225,,,E, +EZE00100082,17880619,TMAX,285,,,E, +EZE00100082,17880619,TMIN,173,,,E, +ITE00100554,17880619,TMAX,271,,,E, +ITE00100554,17880619,TMIN,215,,,E, +EZE00100082,17880620,TMAX,316,,,E, +EZE00100082,17880620,TMIN,198,,,E, +ITE00100554,17880620,TMAX,275,,,E, +ITE00100554,17880620,TMIN,216,,,E, +EZE00100082,17880621,TMAX,302,,,E, +EZE00100082,17880621,TMIN,210,,,E, +ITE00100554,17880621,TMAX,281,,,E, +ITE00100554,17880621,TMIN,231,,,E, +EZE00100082,17880622,TMAX,240,,,E, +EZE00100082,17880622,TMIN,185,,,E, +ITE00100554,17880622,TMAX,269,,,E, +ITE00100554,17880622,TMIN,219,,,E, +EZE00100082,17880623,TMAX,227,,,E, +EZE00100082,17880623,TMIN,163,,,E, +ITE00100554,17880623,TMAX,259,,,E, +ITE00100554,17880623,TMIN,209,,,E, +EZE00100082,17880624,TMAX,217,,,E, +EZE00100082,17880624,TMIN,153,,,E, +ITE00100554,17880624,TMAX,256,,,E, +ITE00100554,17880624,TMIN,219,,,E, +EZE00100082,17880625,TMAX,229,,,E, +EZE00100082,17880625,TMIN,159,,,E, +ITE00100554,17880625,TMAX,250,,,E, +ITE00100554,17880625,TMIN,200,,,E, +EZE00100082,17880626,TMAX,246,,,E, +EZE00100082,17880626,TMIN,155,,,E, +ITE00100554,17880626,TMAX,253,,,E, +ITE00100554,17880626,TMIN,213,,,E, +EZE00100082,17880627,TMAX,226,,,E, +EZE00100082,17880627,TMIN,154,,,E, +ITE00100554,17880627,TMAX,259,,,E, +ITE00100554,17880627,TMIN,200,,,E, +EZE00100082,17880628,TMAX,298,,,E, +EZE00100082,17880628,TMIN,163,,,E, +ITE00100554,17880628,TMAX,250,,,E, +ITE00100554,17880628,TMIN,215,,,E, +EZE00100082,17880629,TMAX,294,,,E, +EZE00100082,17880629,TMIN,175,,,E, +ITE00100554,17880629,TMAX,246,,,E, +ITE00100554,17880629,TMIN,206,,,E, +EZE00100082,17880630,TMAX,235,,,E, +EZE00100082,17880630,TMIN,174,,,E, +ITE00100554,17880630,TMAX,275,,,E, +ITE00100554,17880630,TMIN,221,,,E, +EZE00100082,17880701,TMAX,240,,,E, +EZE00100082,17880701,TMIN,169,,,E, +ITE00100554,17880701,TMAX,288,,,E, +ITE00100554,17880701,TMIN,219,,,E, +EZE00100082,17880702,TMAX,247,,,E, +EZE00100082,17880702,TMIN,176,,,E, +ITE00100554,17880702,TMAX,294,,,E, +ITE00100554,17880702,TMIN,240,,,E, +EZE00100082,17880703,TMAX,272,,,E, +EZE00100082,17880703,TMIN,175,,,E, +ITE00100554,17880703,TMAX,299,,,E, +ITE00100554,17880703,TMIN,239,,,E, +EZE00100082,17880704,TMAX,290,,,E, +EZE00100082,17880704,TMIN,195,,,E, +ITE00100554,17880704,TMAX,303,,,E, +ITE00100554,17880704,TMIN,238,,,E, +EZE00100082,17880705,TMAX,295,,,E, +EZE00100082,17880705,TMIN,213,,,E, +ITE00100554,17880705,TMAX,300,,,E, +ITE00100554,17880705,TMIN,238,,,E, +EZE00100082,17880706,TMAX,236,,,E, +EZE00100082,17880706,TMIN,180,,,E, +ITE00100554,17880706,TMAX,294,,,E, +ITE00100554,17880706,TMIN,234,,,E, +EZE00100082,17880707,TMAX,227,,,E, +EZE00100082,17880707,TMIN,183,,,E, +ITE00100554,17880707,TMAX,290,,,E, +ITE00100554,17880707,TMIN,240,,,E, +EZE00100082,17880708,TMAX,254,,,E, +EZE00100082,17880708,TMIN,182,,,E, +ITE00100554,17880708,TMAX,300,,,E, +ITE00100554,17880708,TMIN,240,,,E, +EZE00100082,17880709,TMAX,253,,,E, +EZE00100082,17880709,TMIN,188,,,E, +ITE00100554,17880709,TMAX,303,,,E, +ITE00100554,17880709,TMIN,250,,,E, +EZE00100082,17880710,TMAX,293,,,E, +EZE00100082,17880710,TMIN,190,,,E, +ITE00100554,17880710,TMAX,306,,,E, +ITE00100554,17880710,TMIN,250,,,E, +EZE00100082,17880711,TMAX,293,,,E, +EZE00100082,17880711,TMIN,202,,,E, +ITE00100554,17880711,TMAX,328,,,E, +ITE00100554,17880711,TMIN,275,,,E, +EZE00100082,17880712,TMAX,288,,,E, +EZE00100082,17880712,TMIN,207,,,E, +ITE00100554,17880712,TMAX,325,,,E, +ITE00100554,17880712,TMIN,269,,,E, +EZE00100082,17880713,TMAX,304,,,E, +EZE00100082,17880713,TMIN,210,,,E, +ITE00100554,17880713,TMAX,319,,,E, +ITE00100554,17880713,TMIN,275,,,E, +EZE00100082,17880714,TMAX,263,,,E, +EZE00100082,17880714,TMIN,213,,,E, +ITE00100554,17880714,TMAX,316,,,E, +ITE00100554,17880714,TMIN,263,,,E, +EZE00100082,17880715,TMAX,286,,,E, +EZE00100082,17880715,TMIN,193,,,E, +ITE00100554,17880715,TMAX,319,,,E, +ITE00100554,17880715,TMIN,263,,,E, +EZE00100082,17880716,TMAX,315,,,E, +EZE00100082,17880716,TMIN,208,,,E, +ITE00100554,17880716,TMAX,329,,,E, +ITE00100554,17880716,TMIN,271,,,E, +EZE00100082,17880717,TMAX,322,,,E, +EZE00100082,17880717,TMIN,224,,,E, +ITE00100554,17880717,TMAX,329,,,E, +ITE00100554,17880717,TMIN,263,,,E, +EZE00100082,17880718,TMAX,260,,,E, +EZE00100082,17880718,TMIN,184,,,E, +ITE00100554,17880718,TMAX,334,,,E, +ITE00100554,17880718,TMIN,263,,,E, +EZE00100082,17880719,TMAX,260,,,E, +EZE00100082,17880719,TMIN,170,,,E, +ITE00100554,17880719,TMAX,325,,,E, +ITE00100554,17880719,TMIN,261,,,E, +EZE00100082,17880720,TMAX,299,,,E, +EZE00100082,17880720,TMIN,205,,,E, +ITE00100554,17880720,TMAX,331,,,E, +ITE00100554,17880720,TMIN,259,,,E, +EZE00100082,17880721,TMAX,264,,,E, +EZE00100082,17880721,TMIN,196,,,E, +ITE00100554,17880721,TMAX,288,,,E, +ITE00100554,17880721,TMIN,250,,,E, +EZE00100082,17880722,TMAX,280,,,E, +EZE00100082,17880722,TMIN,192,,,E, +ITE00100554,17880722,TMAX,250,,,E, +ITE00100554,17880722,TMIN,231,,,E, +EZE00100082,17880723,TMAX,300,,,E, +EZE00100082,17880723,TMIN,198,,,E, +ITE00100554,17880723,TMAX,281,,,E, +ITE00100554,17880723,TMIN,213,,,E, +EZE00100082,17880724,TMAX,334,,,E, +EZE00100082,17880724,TMIN,200,,,E, +ITE00100554,17880724,TMAX,263,,,E, +ITE00100554,17880724,TMIN,213,,,E, +EZE00100082,17880725,TMAX,211,,,E, +EZE00100082,17880725,TMIN,168,,,E, +ITE00100554,17880725,TMAX,313,,,E, +ITE00100554,17880725,TMIN,206,,,E, +EZE00100082,17880726,TMAX,212,,,E, +EZE00100082,17880726,TMIN,168,,,E, +ITE00100554,17880726,TMAX,281,,,E, +ITE00100554,17880726,TMIN,203,,,E, +EZE00100082,17880727,TMAX,213,,,E, +EZE00100082,17880727,TMIN,158,,,E, +ITE00100554,17880727,TMAX,266,,,E, +ITE00100554,17880727,TMIN,213,,,E, +EZE00100082,17880728,TMAX,233,,,E, +EZE00100082,17880728,TMIN,164,,,E, +ITE00100554,17880728,TMAX,269,,,E, +ITE00100554,17880728,TMIN,203,,I,E, +EZE00100082,17880729,TMAX,237,,,E, +EZE00100082,17880729,TMIN,176,,,E, +ITE00100554,17880729,TMAX,175,,I,E, +ITE00100554,17880729,TMIN,175,,,E, +EZE00100082,17880730,TMAX,244,,,E, +EZE00100082,17880730,TMIN,161,,,E, +ITE00100554,17880730,TMAX,225,,,E, +ITE00100554,17880730,TMIN,169,,,E, +EZE00100082,17880731,TMAX,250,,,E, +EZE00100082,17880731,TMIN,160,,,E, +ITE00100554,17880731,TMAX,250,,,E, +ITE00100554,17880731,TMIN,178,,,E, +EZE00100082,17880801,TMAX,222,,,E, +EZE00100082,17880801,TMIN,159,,,E, +ITE00100554,17880801,TMAX,263,,,E, +ITE00100554,17880801,TMIN,194,,,E, +EZE00100082,17880802,TMAX,180,,,E, +EZE00100082,17880802,TMIN,149,,,E, +ITE00100554,17880802,TMAX,288,,,E, +ITE00100554,17880802,TMIN,194,,,E, +EZE00100082,17880803,TMAX,192,,,E, +EZE00100082,17880803,TMIN,146,,,E, +ITE00100554,17880803,TMAX,270,,,E, +ITE00100554,17880803,TMIN,215,,,E, +EZE00100082,17880804,TMAX,192,,,E, +EZE00100082,17880804,TMIN,145,,,E, +ITE00100554,17880804,TMAX,271,,,E, +ITE00100554,17880804,TMIN,203,,,E, +EZE00100082,17880805,TMAX,175,,,E, +EZE00100082,17880805,TMIN,140,,,E, +ITE00100554,17880805,TMAX,296,,,E, +ITE00100554,17880805,TMIN,213,,,E, +EZE00100082,17880806,TMAX,177,,,E, +EZE00100082,17880806,TMIN,131,,,E, +ITE00100554,17880806,TMAX,259,,,E, +ITE00100554,17880806,TMIN,206,,,E, +EZE00100082,17880807,TMAX,186,,,E, +EZE00100082,17880807,TMIN,147,,,E, +ITE00100554,17880807,TMAX,240,,,E, +ITE00100554,17880807,TMIN,178,,,E, +EZE00100082,17880808,TMAX,195,,,E, +EZE00100082,17880808,TMIN,164,,,E, +ITE00100554,17880808,TMAX,256,,,E, +ITE00100554,17880808,TMIN,175,,,E, +EZE00100082,17880809,TMAX,187,,,E, +EZE00100082,17880809,TMIN,159,,,E, +ITE00100554,17880809,TMAX,288,,,E, +ITE00100554,17880809,TMIN,181,,,E, +EZE00100082,17880810,TMAX,215,,,E, +EZE00100082,17880810,TMIN,167,,,E, +ITE00100554,17880810,TMAX,275,,,E, +ITE00100554,17880810,TMIN,204,,,E, +EZE00100082,17880811,TMAX,224,,,E, +EZE00100082,17880811,TMIN,176,,,E, +ITE00100554,17880811,TMAX,281,,,E, +ITE00100554,17880811,TMIN,216,,,E, +EZE00100082,17880812,TMAX,232,,,E, +EZE00100082,17880812,TMIN,174,,,E, +ITE00100554,17880812,TMAX,256,,,E, +ITE00100554,17880812,TMIN,228,,,E, +EZE00100082,17880813,TMAX,236,,,E, +EZE00100082,17880813,TMIN,173,,,E, +ITE00100554,17880813,TMAX,263,,,E, +ITE00100554,17880813,TMIN,194,,,E, +EZE00100082,17880814,TMAX,225,,,E, +EZE00100082,17880814,TMIN,193,,,E, +ITE00100554,17880814,TMAX,263,,,E, +ITE00100554,17880814,TMIN,228,,,E, +EZE00100082,17880815,TMAX,210,,,E, +EZE00100082,17880815,TMIN,168,,,E, +ITE00100554,17880815,TMAX,275,,,E, +ITE00100554,17880815,TMIN,184,,,E, +EZE00100082,17880816,TMAX,210,,,E, +EZE00100082,17880816,TMIN,159,,,E, +ITE00100554,17880816,TMAX,269,,,E, +ITE00100554,17880816,TMIN,196,,,E, +EZE00100082,17880817,TMAX,228,,,E, +EZE00100082,17880817,TMIN,161,,,E, +ITE00100554,17880817,TMAX,266,,,E, +ITE00100554,17880817,TMIN,196,,,E, +EZE00100082,17880818,TMAX,226,,,E, +EZE00100082,17880818,TMIN,182,,,E, +ITE00100554,17880818,TMAX,288,,,E, +ITE00100554,17880818,TMIN,200,,,E, +EZE00100082,17880819,TMAX,230,,,E, +EZE00100082,17880819,TMIN,164,,,E, +ITE00100554,17880819,TMAX,269,,,E, +ITE00100554,17880819,TMIN,225,,,E, +EZE00100082,17880820,TMAX,226,,,E, +EZE00100082,17880820,TMIN,166,,,E, +ITE00100554,17880820,TMAX,270,,,E, +ITE00100554,17880820,TMIN,204,,,E, +EZE00100082,17880821,TMAX,214,,,E, +EZE00100082,17880821,TMIN,164,,,E, +ITE00100554,17880821,TMAX,269,,,E, +ITE00100554,17880821,TMIN,206,,,E, +EZE00100082,17880822,TMAX,232,,,E, +EZE00100082,17880822,TMIN,155,,,E, +ITE00100554,17880822,TMAX,265,,,E, +ITE00100554,17880822,TMIN,196,,,E, +EZE00100082,17880823,TMAX,242,,,E, +EZE00100082,17880823,TMIN,168,,,E, +ITE00100554,17880823,TMAX,256,,,E, +ITE00100554,17880823,TMIN,200,,,E, +EZE00100082,17880824,TMAX,238,,,E, +EZE00100082,17880824,TMIN,178,,,E, +ITE00100554,17880824,TMAX,256,,,E, +ITE00100554,17880824,TMIN,190,,,E, +EZE00100082,17880825,TMAX,220,,,E, +EZE00100082,17880825,TMIN,176,,,E, +ITE00100554,17880825,TMAX,259,,,E, +ITE00100554,17880825,TMIN,194,,,E, +EZE00100082,17880826,TMAX,217,,,E, +EZE00100082,17880826,TMIN,162,,,E, +ITE00100554,17880826,TMAX,266,,,E, +ITE00100554,17880826,TMIN,206,,,E, +EZE00100082,17880827,TMAX,215,,,E, +EZE00100082,17880827,TMIN,173,,,E, +ITE00100554,17880827,TMAX,206,,,E, +ITE00100554,17880827,TMIN,190,,,E, +EZE00100082,17880828,TMAX,184,,,E, +EZE00100082,17880828,TMIN,146,,,E, +ITE00100554,17880828,TMAX,238,,,E, +ITE00100554,17880828,TMIN,166,,,E, +EZE00100082,17880829,TMAX,210,,,E, +EZE00100082,17880829,TMIN,151,,,E, +ITE00100554,17880829,TMAX,238,,,E, +ITE00100554,17880829,TMIN,156,,,E, +EZE00100082,17880830,TMAX,192,,,E, +EZE00100082,17880830,TMIN,145,,,E, +ITE00100554,17880830,TMAX,238,,,E, +ITE00100554,17880830,TMIN,169,,,E, +EZE00100082,17880831,TMAX,205,,,E, +EZE00100082,17880831,TMIN,143,,,E, +ITE00100554,17880831,TMAX,244,,,E, +ITE00100554,17880831,TMIN,181,,,E, +EZE00100082,17880901,TMAX,212,,,E, +EZE00100082,17880901,TMIN,160,,,E, +ITE00100554,17880901,TMAX,250,,,E, +ITE00100554,17880901,TMIN,181,,,E, +EZE00100082,17880902,TMAX,189,,,E, +EZE00100082,17880902,TMIN,157,,,E, +ITE00100554,17880902,TMAX,250,,,E, +ITE00100554,17880902,TMIN,181,,,E, +EZE00100082,17880903,TMAX,210,,,E, +EZE00100082,17880903,TMIN,157,,,E, +ITE00100554,17880903,TMAX,256,,,E, +ITE00100554,17880903,TMIN,194,,,E, +EZE00100082,17880904,TMAX,216,,,E, +EZE00100082,17880904,TMIN,128,,,E, +ITE00100554,17880904,TMAX,263,,,E, +ITE00100554,17880904,TMIN,191,,,E, +EZE00100082,17880905,TMAX,228,,,E, +EZE00100082,17880905,TMIN,130,,,E, +ITE00100554,17880905,TMAX,269,,,E, +ITE00100554,17880905,TMIN,194,,,E, +EZE00100082,17880906,TMAX,252,,,E, +EZE00100082,17880906,TMIN,160,,,E, +ITE00100554,17880906,TMAX,275,,,E, +ITE00100554,17880906,TMIN,269,,,E, +EZE00100082,17880907,TMAX,235,,,E, +EZE00100082,17880907,TMIN,162,,,E, +ITE00100554,17880907,TMAX,275,,,E, +ITE00100554,17880907,TMIN,198,,,E, +EZE00100082,17880908,TMAX,238,,,E, +EZE00100082,17880908,TMIN,149,,,E, +ITE00100554,17880908,TMAX,269,,,E, +ITE00100554,17880908,TMIN,213,,,E, +EZE00100082,17880909,TMAX,235,,,E, +EZE00100082,17880909,TMIN,151,,,E, +ITE00100554,17880909,TMAX,219,,,E, +ITE00100554,17880909,TMIN,213,,,E, +EZE00100082,17880910,TMAX,262,,,E, +EZE00100082,17880910,TMIN,157,,,E, +ITE00100554,17880910,TMAX,225,,,E, +ITE00100554,17880910,TMIN,178,,,E, +EZE00100082,17880911,TMAX,263,,,E, +EZE00100082,17880911,TMIN,127,,,E, +ITE00100554,17880911,TMAX,244,,,E, +ITE00100554,17880911,TMIN,190,,,E, +EZE00100082,17880912,TMAX,223,,,E, +EZE00100082,17880912,TMIN,100,,,E, +ITE00100554,17880912,TMAX,256,,,E, +ITE00100554,17880912,TMIN,188,,,E, +EZE00100082,17880913,TMAX,262,,,E, +EZE00100082,17880913,TMIN,122,,,E, +ITE00100554,17880913,TMAX,194,,,E, +ITE00100554,17880913,TMIN,181,,,E, +EZE00100082,17880914,TMAX,250,,,E, +EZE00100082,17880914,TMIN,120,,,E, +ITE00100554,17880914,TMAX,231,,,E, +ITE00100554,17880914,TMIN,165,,,E, +EZE00100082,17880915,TMAX,167,,,E, +EZE00100082,17880915,TMIN,118,,,E, +ITE00100554,17880915,TMAX,228,,,E, +ITE00100554,17880915,TMIN,178,,,E, +EZE00100082,17880916,TMAX,191,,,E, +EZE00100082,17880916,TMIN,107,,,E, +ITE00100554,17880916,TMAX,219,,,E, +ITE00100554,17880916,TMIN,181,,,E, +EZE00100082,17880917,TMAX,192,,,E, +EZE00100082,17880917,TMIN,80,,,E, +ITE00100554,17880917,TMAX,213,,,E, +ITE00100554,17880917,TMIN,181,,,E, +EZE00100082,17880918,TMAX,188,,,E, +EZE00100082,17880918,TMIN,80,,,E, +ITE00100554,17880918,TMAX,181,,,E, +ITE00100554,17880918,TMIN,175,,,E, +EZE00100082,17880919,TMAX,161,,,E, +EZE00100082,17880919,TMIN,119,,,E, +ITE00100554,17880919,TMAX,219,,,E, +ITE00100554,17880919,TMIN,163,,,E, +EZE00100082,17880920,TMAX,153,,,E, +EZE00100082,17880920,TMIN,102,,,E, +ITE00100554,17880920,TMAX,206,,,E, +ITE00100554,17880920,TMIN,175,,,E, +EZE00100082,17880921,TMAX,173,,,E, +EZE00100082,17880921,TMIN,112,,,E, +ITE00100554,17880921,TMAX,219,,,E, +ITE00100554,17880921,TMIN,181,,,E, +EZE00100082,17880922,TMAX,201,,,E, +EZE00100082,17880922,TMIN,93,,,E, +ITE00100554,17880922,TMAX,225,,,E, +ITE00100554,17880922,TMIN,175,,,E, +EZE00100082,17880923,TMAX,200,,,E, +EZE00100082,17880923,TMIN,103,,,E, +ITE00100554,17880923,TMAX,225,,,E, +ITE00100554,17880923,TMIN,163,,,E, +EZE00100082,17880924,TMAX,207,,,E, +EZE00100082,17880924,TMIN,125,,,E, +ITE00100554,17880924,TMAX,213,,,E, +ITE00100554,17880924,TMIN,163,,,E, +EZE00100082,17880925,TMAX,191,,,E, +EZE00100082,17880925,TMIN,120,,,E, +ITE00100554,17880925,TMAX,213,,,E, +ITE00100554,17880925,TMIN,175,,,E, +EZE00100082,17880926,TMAX,163,,,E, +EZE00100082,17880926,TMIN,99,,,E, +ITE00100554,17880926,TMAX,200,,,E, +ITE00100554,17880926,TMIN,150,,,E, +EZE00100082,17880927,TMAX,200,,,E, +EZE00100082,17880927,TMIN,85,,,E, +ITE00100554,17880927,TMAX,213,,,E, +ITE00100554,17880927,TMIN,125,,,E, +EZE00100082,17880928,TMAX,190,,,E, +EZE00100082,17880928,TMIN,80,,,E, +ITE00100554,17880928,TMAX,213,,,E, +ITE00100554,17880928,TMIN,153,,,E, +EZE00100082,17880929,TMAX,185,,,E, +EZE00100082,17880929,TMIN,99,,,E, +ITE00100554,17880929,TMAX,200,,,E, +ITE00100554,17880929,TMIN,175,,,E, +EZE00100082,17880930,TMAX,173,,,E, +EZE00100082,17880930,TMIN,122,,,E, +ITE00100554,17880930,TMAX,203,,,E, +ITE00100554,17880930,TMIN,163,,,E, +EZE00100082,17881001,TMAX,148,,,E, +EZE00100082,17881001,TMIN,121,,,E, +ITE00100554,17881001,TMAX,200,,,E, +ITE00100554,17881001,TMIN,128,,,E, +EZE00100082,17881002,TMAX,181,,,E, +EZE00100082,17881002,TMIN,125,,,E, +ITE00100554,17881002,TMAX,200,,,E, +ITE00100554,17881002,TMIN,138,,,E, +EZE00100082,17881003,TMAX,214,,,E, +EZE00100082,17881003,TMIN,163,,,E, +ITE00100554,17881003,TMAX,206,,,E, +ITE00100554,17881003,TMIN,144,,,E, +EZE00100082,17881004,TMAX,190,,,E, +EZE00100082,17881004,TMIN,140,,,E, +ITE00100554,17881004,TMAX,215,,,E, +ITE00100554,17881004,TMIN,153,,,E, +EZE00100082,17881005,TMAX,190,,,E, +EZE00100082,17881005,TMIN,123,,,E, +ITE00100554,17881005,TMAX,225,,,E, +ITE00100554,17881005,TMIN,156,,,E, +EZE00100082,17881006,TMAX,192,,,E, +EZE00100082,17881006,TMIN,118,,,E, +ITE00100554,17881006,TMAX,225,,,E, +ITE00100554,17881006,TMIN,159,,,E, +EZE00100082,17881007,TMAX,152,,,E, +EZE00100082,17881007,TMIN,115,,,E, +ITE00100554,17881007,TMAX,223,,,E, +ITE00100554,17881007,TMIN,178,,,E, +EZE00100082,17881008,TMAX,115,,,E, +EZE00100082,17881008,TMIN,85,,,E, +ITE00100554,17881008,TMAX,209,,,E, +ITE00100554,17881008,TMIN,188,,,E, +EZE00100082,17881009,TMAX,135,,,E, +EZE00100082,17881009,TMIN,72,,,E, +ITE00100554,17881009,TMAX,206,,,E, +ITE00100554,17881009,TMIN,175,,I,E, +EZE00100082,17881010,TMAX,137,,,E, +EZE00100082,17881010,TMIN,62,,,E, +ITE00100554,17881010,TMAX,156,,I,E, +ITE00100554,17881010,TMIN,131,,,E, +EZE00100082,17881011,TMAX,134,,,E, +EZE00100082,17881011,TMIN,60,,,E, +ITE00100554,17881011,TMAX,156,,,E, +ITE00100554,17881011,TMIN,94,,,E, +EZE00100082,17881012,TMAX,130,,,E, +EZE00100082,17881012,TMIN,62,,,E, +ITE00100554,17881012,TMAX,156,,,E, +ITE00100554,17881012,TMIN,94,,,E, +EZE00100082,17881013,TMAX,99,,,E, +EZE00100082,17881013,TMIN,55,,,E, +ITE00100554,17881013,TMAX,175,,,E, +ITE00100554,17881013,TMIN,98,,,E, +EZE00100082,17881014,TMAX,110,,,E, +EZE00100082,17881014,TMIN,62,,,E, +ITE00100554,17881014,TMAX,181,,,E, +ITE00100554,17881014,TMIN,104,,,E, +EZE00100082,17881015,TMAX,102,,,E, +EZE00100082,17881015,TMIN,23,,,E, +ITE00100554,17881015,TMAX,138,,,E, +ITE00100554,17881015,TMIN,138,,,E, +EZE00100082,17881016,TMAX,111,,,E, +EZE00100082,17881016,TMIN,35,,,E, +ITE00100554,17881016,TMAX,150,,,E, +ITE00100554,17881016,TMIN,138,,,E, +EZE00100082,17881017,TMAX,139,,,E, +EZE00100082,17881017,TMIN,95,,,E, +ITE00100554,17881017,TMAX,163,,,E, +ITE00100554,17881017,TMIN,106,,,E, +EZE00100082,17881018,TMAX,95,,,E, +EZE00100082,17881018,TMIN,66,,,E, +ITE00100554,17881018,TMAX,171,,,E, +ITE00100554,17881018,TMIN,100,,,E, +EZE00100082,17881019,TMAX,92,,,E, +EZE00100082,17881019,TMIN,33,,,E, +ITE00100554,17881019,TMAX,134,,,E, +ITE00100554,17881019,TMIN,106,,,E, +EZE00100082,17881020,TMAX,93,,,E, +EZE00100082,17881020,TMIN,44,,,E, +ITE00100554,17881020,TMAX,125,,,E, +ITE00100554,17881020,TMIN,63,,,E, +EZE00100082,17881021,TMAX,121,,,E, +EZE00100082,17881021,TMIN,60,,,E, +ITE00100554,17881021,TMAX,144,,,E, +ITE00100554,17881021,TMIN,69,,,E, +EZE00100082,17881022,TMAX,122,,,E, +EZE00100082,17881022,TMIN,91,,,E, +ITE00100554,17881022,TMAX,163,,,E, +ITE00100554,17881022,TMIN,88,,,E, +EZE00100082,17881023,TMAX,109,,,E, +EZE00100082,17881023,TMIN,80,,,E, +ITE00100554,17881023,TMAX,150,,,E, +ITE00100554,17881023,TMIN,88,,,E, +EZE00100082,17881024,TMAX,107,,,E, +EZE00100082,17881024,TMIN,84,,,E, +ITE00100554,17881024,TMAX,150,,,E, +ITE00100554,17881024,TMIN,94,,,E, +EZE00100082,17881025,TMAX,85,,,E, +EZE00100082,17881025,TMIN,66,,,E, +ITE00100554,17881025,TMAX,138,,,E, +ITE00100554,17881025,TMIN,71,,,E, +EZE00100082,17881026,TMAX,88,,,E, +EZE00100082,17881026,TMIN,52,,,E, +ITE00100554,17881026,TMAX,134,,,E, +ITE00100554,17881026,TMIN,70,,,E, +EZE00100082,17881027,TMAX,95,,,E, +EZE00100082,17881027,TMIN,81,,,E, +ITE00100554,17881027,TMAX,131,,,E, +ITE00100554,17881027,TMIN,59,,,E, +EZE00100082,17881028,TMAX,110,,,E, +EZE00100082,17881028,TMIN,74,,,E, +ITE00100554,17881028,TMAX,133,,,E, +ITE00100554,17881028,TMIN,100,,,E, +EZE00100082,17881029,TMAX,103,,,E, +EZE00100082,17881029,TMIN,69,,,E, +ITE00100554,17881029,TMAX,96,,,E, +ITE00100554,17881029,TMIN,70,,,E, +EZE00100082,17881030,TMAX,87,,,E, +EZE00100082,17881030,TMIN,61,,,E, +ITE00100554,17881030,TMAX,100,,,E, +ITE00100554,17881030,TMIN,88,,,E, +EZE00100082,17881031,TMAX,82,,,E, +EZE00100082,17881031,TMIN,29,,,E, +ITE00100554,17881031,TMAX,125,,,E, +ITE00100554,17881031,TMIN,91,,,E, +EZE00100082,17881101,TMAX,97,,,E, +EZE00100082,17881101,TMIN,70,,,E, +ITE00100554,17881101,TMAX,89,,,E, +ITE00100554,17881101,TMIN,44,,,E, +EZE00100082,17881102,TMAX,100,,,E, +EZE00100082,17881102,TMIN,55,,,E, +ITE00100554,17881102,TMAX,113,,,E, +ITE00100554,17881102,TMIN,81,,,E, +EZE00100082,17881103,TMAX,104,,,E, +EZE00100082,17881103,TMIN,28,,,E, +ITE00100554,17881103,TMAX,106,,,E, +ITE00100554,17881103,TMIN,34,,,E, +EZE00100082,17881104,TMAX,119,,,E, +EZE00100082,17881104,TMIN,53,,,E, +ITE00100554,17881104,TMAX,106,,,E, +ITE00100554,17881104,TMIN,34,,,E, +EZE00100082,17881105,TMAX,105,,,E, +EZE00100082,17881105,TMIN,70,,,E, +ITE00100554,17881105,TMAX,106,,,E, +ITE00100554,17881105,TMIN,81,,,E, +EZE00100082,17881106,TMAX,77,,,E, +EZE00100082,17881106,TMIN,45,,,E, +ITE00100554,17881106,TMAX,113,,,E, +ITE00100554,17881106,TMIN,100,,,E, +EZE00100082,17881107,TMAX,49,,,E, +EZE00100082,17881107,TMIN,10,,,E, +ITE00100554,17881107,TMAX,108,,,E, +ITE00100554,17881107,TMIN,81,,,E, +EZE00100082,17881108,TMAX,101,,,E, +EZE00100082,17881108,TMIN,16,,,E, +ITE00100554,17881108,TMAX,100,,,E, +ITE00100554,17881108,TMIN,56,,,E, +EZE00100082,17881109,TMAX,66,,,E, +EZE00100082,17881109,TMIN,3,,,E, +ITE00100554,17881109,TMAX,106,,,E, +ITE00100554,17881109,TMIN,75,,,E, +EZE00100082,17881110,TMAX,82,,,E, +EZE00100082,17881110,TMIN,24,,,E, +ITE00100554,17881110,TMAX,100,,,E, +ITE00100554,17881110,TMIN,90,,,E, +EZE00100082,17881111,TMAX,81,,,E, +EZE00100082,17881111,TMIN,27,,,E, +ITE00100554,17881111,TMAX,131,,,E, +ITE00100554,17881111,TMIN,96,,,E, +EZE00100082,17881112,TMAX,119,,,E, +EZE00100082,17881112,TMIN,41,,,E, +ITE00100554,17881112,TMAX,140,,,E, +ITE00100554,17881112,TMIN,100,,,E, +EZE00100082,17881113,TMAX,125,,,E, +EZE00100082,17881113,TMIN,69,,,E, +ITE00100554,17881113,TMAX,141,,,E, +ITE00100554,17881113,TMIN,91,,,E, +EZE00100082,17881114,TMAX,112,,,E, +EZE00100082,17881114,TMIN,46,,,E, +ITE00100554,17881114,TMAX,119,,,E, +ITE00100554,17881114,TMIN,115,,I,E, +EZE00100082,17881115,TMAX,69,,,E, +EZE00100082,17881115,TMIN,29,,,E, +ITE00100554,17881115,TMAX,103,,I,E, +ITE00100554,17881115,TMIN,79,,,E, +EZE00100082,17881116,TMAX,45,,,E, +EZE00100082,17881116,TMIN,5,,,E, +ITE00100554,17881116,TMAX,79,,,E, +ITE00100554,17881116,TMIN,60,,,E, +EZE00100082,17881117,TMAX,40,,,E, +EZE00100082,17881117,TMIN,-6,,,E, +ITE00100554,17881117,TMAX,79,,,E, +ITE00100554,17881117,TMIN,65,,,E, +EZE00100082,17881118,TMAX,45,,,E, +EZE00100082,17881118,TMIN,26,,,E, +ITE00100554,17881118,TMAX,78,,,E, +ITE00100554,17881118,TMIN,59,,,E, +EZE00100082,17881119,TMAX,37,,,E, +EZE00100082,17881119,TMIN,22,,,E, +ITE00100554,17881119,TMAX,90,,,E, +ITE00100554,17881119,TMIN,53,,,E, +EZE00100082,17881120,TMAX,33,,,E, +EZE00100082,17881120,TMIN,12,,,E, +ITE00100554,17881120,TMAX,56,,,E, +ITE00100554,17881120,TMIN,25,,,E, +EZE00100082,17881121,TMAX,38,,,E, +EZE00100082,17881121,TMIN,-5,,,E, +ITE00100554,17881121,TMAX,78,,,E, +ITE00100554,17881121,TMIN,46,,,E, +EZE00100082,17881122,TMAX,61,,,E, +EZE00100082,17881122,TMIN,28,,,E, +ITE00100554,17881122,TMAX,50,,,E, +ITE00100554,17881122,TMIN,13,,,E, +EZE00100082,17881123,TMAX,28,,,E, +EZE00100082,17881123,TMIN,9,,,E, +ITE00100554,17881123,TMAX,59,,,E, +ITE00100554,17881123,TMIN,25,,,E, +EZE00100082,17881124,TMAX,9,,,E, +EZE00100082,17881124,TMIN,-36,,,E, +ITE00100554,17881124,TMAX,63,,,E, +ITE00100554,17881124,TMIN,46,,,E, +EZE00100082,17881125,TMAX,-28,,,E, +EZE00100082,17881125,TMIN,-62,,,E, +ITE00100554,17881125,TMAX,50,,,E, +ITE00100554,17881125,TMIN,19,,I,E, +EZE00100082,17881126,TMAX,-41,,,E, +EZE00100082,17881126,TMIN,-72,,,E, +ITE00100554,17881126,TMAX,-13,,I,E, +ITE00100554,17881126,TMIN,-25,,,E, +EZE00100082,17881127,TMAX,0,,,E, +EZE00100082,17881127,TMIN,-41,,,E, +ITE00100554,17881127,TMAX,-15,,,E, +ITE00100554,17881127,TMIN,-28,,,E, +EZE00100082,17881128,TMAX,11,,,E, +EZE00100082,17881128,TMIN,-8,,,E, +ITE00100554,17881128,TMAX,-9,,,E, +ITE00100554,17881128,TMIN,-21,,,E, +EZE00100082,17881129,TMAX,11,,,E, +EZE00100082,17881129,TMIN,-17,,,E, +ITE00100554,17881129,TMAX,-8,,,E, +ITE00100554,17881129,TMIN,-81,,,E, +EZE00100082,17881130,TMAX,-17,,,E, +EZE00100082,17881130,TMIN,-63,,,E, +ITE00100554,17881130,TMAX,0,,N,E, +ITE00100554,17881130,TMIN,0,,N,E, +EZE00100082,17881201,TMAX,-26,,,E, +EZE00100082,17881201,TMIN,-100,,,E, +ITE00100554,17881201,TMAX,38,,,E, +ITE00100554,17881201,TMIN,25,,,E, +EZE00100082,17881202,TMAX,-35,,,E, +EZE00100082,17881202,TMIN,-62,,,E, +ITE00100554,17881202,TMAX,38,,,E, +ITE00100554,17881202,TMIN,8,,,E, +EZE00100082,17881203,TMAX,-38,,,E, +EZE00100082,17881203,TMIN,-51,,,E, +ITE00100554,17881203,TMAX,38,,,E, +ITE00100554,17881203,TMIN,13,,,E, +EZE00100082,17881204,TMAX,-37,,,E, +EZE00100082,17881204,TMIN,-49,,,E, +ITE00100554,17881204,TMAX,38,,,E, +ITE00100554,17881204,TMIN,19,,,E, +EZE00100082,17881205,TMAX,-20,,,E, +EZE00100082,17881205,TMIN,-50,,,E, +ITE00100554,17881205,TMAX,38,,,E, +ITE00100554,17881205,TMIN,25,,,E, +EZE00100082,17881206,TMAX,-23,,,E, +EZE00100082,17881206,TMIN,-41,,,E, +ITE00100554,17881206,TMAX,63,,,E, +ITE00100554,17881206,TMIN,33,,,E, +EZE00100082,17881207,TMAX,-41,,,E, +EZE00100082,17881207,TMIN,-67,,,E, +ITE00100554,17881207,TMAX,75,,,E, +ITE00100554,17881207,TMIN,70,,,E, +EZE00100082,17881208,TMAX,-62,,,E, +EZE00100082,17881208,TMIN,-96,,,E, +ITE00100554,17881208,TMAX,75,,,E, +ITE00100554,17881208,TMIN,70,,,E, +EZE00100082,17881209,TMAX,-96,,,E, +EZE00100082,17881209,TMIN,-141,,,E, +ITE00100554,17881209,TMAX,75,,,E, +ITE00100554,17881209,TMIN,63,,,E, +EZE00100082,17881210,TMAX,-50,,,E, +EZE00100082,17881210,TMIN,-148,,,E, +ITE00100554,17881210,TMAX,56,,,E, +ITE00100554,17881210,TMIN,50,,,E, +EZE00100082,17881211,TMAX,-18,,,E, +EZE00100082,17881211,TMIN,-50,,,E, +ITE00100554,17881211,TMAX,53,,,E, +ITE00100554,17881211,TMIN,46,,,E, +EZE00100082,17881212,TMAX,-35,,,E, +EZE00100082,17881212,TMIN,-66,,,E, +ITE00100554,17881212,TMAX,50,,,E, +ITE00100554,17881212,TMIN,8,,,E, +EZE00100082,17881213,TMAX,-66,,,E, +EZE00100082,17881213,TMIN,-123,,,E, +ITE00100554,17881213,TMAX,38,,,E, +ITE00100554,17881213,TMIN,9,,,E, +EZE00100082,17881214,TMAX,-123,,,E, +EZE00100082,17881214,TMIN,-161,,,E, +ITE00100554,17881214,TMAX,8,,,E, +ITE00100554,17881214,TMIN,6,,,E, +EZE00100082,17881215,TMAX,-101,,,E, +EZE00100082,17881215,TMIN,-136,,,E, +ITE00100554,17881215,TMAX,13,,,E, +ITE00100554,17881215,TMIN,0,,,E, +EZE00100082,17881216,TMAX,-127,,,E, +EZE00100082,17881216,TMIN,-190,,,E, +ITE00100554,17881216,TMAX,13,,,E, +ITE00100554,17881216,TMIN,4,,,E, +EZE00100082,17881217,TMAX,-177,,,E, +EZE00100082,17881217,TMIN,-238,,,E, +ITE00100554,17881217,TMAX,16,,,E, +ITE00100554,17881217,TMIN,8,,,E, +EZE00100082,17881218,TMAX,-163,,,E, +EZE00100082,17881218,TMIN,-204,,,E, +ITE00100554,17881218,TMAX,9,,,E, +ITE00100554,17881218,TMIN,0,,,E, +EZE00100082,17881219,TMAX,-146,,,E, +EZE00100082,17881219,TMIN,-228,,,E, +ITE00100554,17881219,TMAX,-6,,,E, +ITE00100554,17881219,TMIN,-13,,,E, +EZE00100082,17881220,TMAX,-89,,,E, +EZE00100082,17881220,TMIN,-153,,,E, +ITE00100554,17881220,TMAX,0,,,E, +ITE00100554,17881220,TMIN,-25,,,E, +EZE00100082,17881221,TMAX,-34,,,E, +EZE00100082,17881221,TMIN,-89,,,E, +ITE00100554,17881221,TMAX,0,,,E, +ITE00100554,17881221,TMIN,-34,,,E, +EZE00100082,17881222,TMAX,-29,,,E, +EZE00100082,17881222,TMIN,-67,,,E, +ITE00100554,17881222,TMAX,-8,,,E, +ITE00100554,17881222,TMIN,-44,,,E, +EZE00100082,17881223,TMAX,-67,,,E, +EZE00100082,17881223,TMIN,-113,,,E, +ITE00100554,17881223,TMAX,0,,,E, +ITE00100554,17881223,TMIN,-20,,,E, +EZE00100082,17881224,TMAX,-33,,,E, +EZE00100082,17881224,TMIN,-122,,,E, +ITE00100554,17881224,TMAX,-25,,I,E, +ITE00100554,17881224,TMIN,-50,,,E, +EZE00100082,17881225,TMAX,24,,,E, +EZE00100082,17881225,TMIN,-34,,,E, +ITE00100554,17881225,TMAX,56,,,E, +ITE00100554,17881225,TMIN,-8,,I,E, +EZE00100082,17881226,TMAX,-34,,,E, +EZE00100082,17881226,TMIN,-142,,,E, +ITE00100554,17881226,TMAX,16,,,E, +ITE00100554,17881226,TMIN,8,,I,E, +EZE00100082,17881227,TMAX,-142,,,E, +EZE00100082,17881227,TMIN,-191,,,E, +ITE00100554,17881227,TMAX,-13,,I,E, +ITE00100554,17881227,TMIN,-25,,I,E, +EZE00100082,17881228,TMAX,-157,,,E, +EZE00100082,17881228,TMIN,-213,,,E, +ITE00100554,17881228,TMAX,-45,,I,E, +ITE00100554,17881228,TMIN,-58,,,E, +EZE00100082,17881229,TMAX,-135,,,E, +EZE00100082,17881229,TMIN,-171,,,E, +ITE00100554,17881229,TMAX,-28,,,E, +ITE00100554,17881229,TMIN,-50,,I,E, +EZE00100082,17881230,TMAX,-120,,,E, +EZE00100082,17881230,TMIN,-175,,,E, +ITE00100554,17881230,TMAX,-65,,I,E, +ITE00100554,17881230,TMIN,-103,,,E, +EZE00100082,17881231,TMAX,-115,,,E, +EZE00100082,17881231,TMIN,-140,,,E, +ITE00100554,17881231,TMAX,-54,,,E, +ITE00100554,17881231,TMIN,-105,,,E, +EZE00100082,17890101,TMAX,-103,,,E, +EZE00100082,17890101,TMIN,-184,,,E, +ITE00100554,17890101,TMAX,-63,,,E, +ITE00100554,17890101,TMIN,-90,,,E, +GM000010962,17890101,PRCP,4,,,E, +EZE00100082,17890102,TMAX,-98,,,E, +EZE00100082,17890102,TMIN,-170,,,E, +ITE00100554,17890102,TMAX,-16,,,E, +ITE00100554,17890102,TMIN,-66,,,E, +GM000010962,17890102,PRCP,15,,,E, +EZE00100082,17890103,TMAX,-105,,,E, +EZE00100082,17890103,TMIN,-157,,,E, +ITE00100554,17890103,TMAX,-13,,,E, +ITE00100554,17890103,TMIN,-71,,,E, +GM000010962,17890103,PRCP,17,,,E, +EZE00100082,17890104,TMAX,-157,,,E, +EZE00100082,17890104,TMIN,-218,,,E, +ITE00100554,17890104,TMAX,-31,,,E, +ITE00100554,17890104,TMIN,-75,,,E, +GM000010962,17890104,PRCP,0,,,E, +EZE00100082,17890105,TMAX,-113,,,E, +EZE00100082,17890105,TMIN,-272,,,E, +ITE00100554,17890105,TMAX,-31,,,E, +ITE00100554,17890105,TMIN,-94,,,E, +GM000010962,17890105,PRCP,0,,,E, +EZE00100082,17890106,TMAX,-122,,,E, +EZE00100082,17890106,TMIN,-224,,,E, +ITE00100554,17890106,TMAX,-46,,,E, +ITE00100554,17890106,TMIN,-59,,,E, +GM000010962,17890106,PRCP,17,,,E, +EZE00100082,17890107,TMAX,-198,,,E, +EZE00100082,17890107,TMIN,-251,,,E, +ITE00100554,17890107,TMAX,-59,,,E, +ITE00100554,17890107,TMIN,-100,,,E, +GM000010962,17890107,PRCP,0,,,E, +EZE00100082,17890108,TMAX,-200,,,E, +EZE00100082,17890108,TMIN,-254,,,E, +ITE00100554,17890108,TMAX,-38,,,E, +ITE00100554,17890108,TMIN,-53,,,E, +GM000010962,17890108,PRCP,0,,,E, +EZE00100082,17890109,TMAX,-172,,,E, +EZE00100082,17890109,TMIN,-270,,,E, +ITE00100554,17890109,TMAX,-13,,,E, +ITE00100554,17890109,TMIN,-34,,,E, +GM000010962,17890109,PRCP,0,,,E, +EZE00100082,17890110,TMAX,-117,,,E, +EZE00100082,17890110,TMIN,-172,,,E, +ITE00100554,17890110,TMAX,-10,,,E, +ITE00100554,17890110,TMIN,-25,,,E, +GM000010962,17890110,PRCP,0,,,E, +EZE00100082,17890111,TMAX,-77,,,E, +EZE00100082,17890111,TMIN,-150,,,E, +ITE00100554,17890111,TMAX,0,,,E, +ITE00100554,17890111,TMIN,-31,,,E, +GM000010962,17890111,PRCP,39,,,E, +EZE00100082,17890112,TMAX,-42,,,E, +EZE00100082,17890112,TMIN,-83,,,E, +ITE00100554,17890112,TMAX,20,,,E, +ITE00100554,17890112,TMIN,0,,,E, +GM000010962,17890112,PRCP,3,,,E, +EZE00100082,17890113,TMAX,-63,,,E, +EZE00100082,17890113,TMIN,-134,,,E, +ITE00100554,17890113,TMAX,0,,,E, +ITE00100554,17890113,TMIN,-31,,,E, +GM000010962,17890113,PRCP,0,,,E, +EZE00100082,17890114,TMAX,-28,,,E, +EZE00100082,17890114,TMIN,-88,,,E, +ITE00100554,17890114,TMAX,0,,N,E, +ITE00100554,17890114,TMIN,0,,N,E, +GM000010962,17890114,PRCP,0,,,E, +EZE00100082,17890115,TMAX,14,,,E, +EZE00100082,17890115,TMIN,-61,,,E, +ITE00100554,17890115,TMAX,13,,,E, +ITE00100554,17890115,TMIN,4,,,E, +GM000010962,17890115,PRCP,6,,,E, +EZE00100082,17890116,TMAX,50,,,E, +EZE00100082,17890116,TMIN,8,,,E, +ITE00100554,17890116,TMAX,25,,,E, +ITE00100554,17890116,TMIN,-20,,,E, +GM000010962,17890116,PRCP,0,,,E, +EZE00100082,17890117,TMAX,23,,,E, +EZE00100082,17890117,TMIN,-8,,,E, +ITE00100554,17890117,TMAX,13,,,E, +ITE00100554,17890117,TMIN,-13,,,E, +GM000010962,17890117,PRCP,0,,,E, +EZE00100082,17890118,TMAX,17,,,E, +EZE00100082,17890118,TMIN,-44,,,E, +ITE00100554,17890118,TMAX,9,,,E, +ITE00100554,17890118,TMIN,0,,,E, +GM000010962,17890118,PRCP,0,,,E, +EZE00100082,17890119,TMAX,57,,,E, +EZE00100082,17890119,TMIN,-44,,,E, +ITE00100554,17890119,TMAX,19,,,E, +ITE00100554,17890119,TMIN,0,,,E, +GM000010962,17890119,PRCP,0,,,E, +EZE00100082,17890120,TMAX,30,,,E, +EZE00100082,17890120,TMIN,-22,,,E, +ITE00100554,17890120,TMAX,25,,,E, +ITE00100554,17890120,TMIN,8,,,E, +GM000010962,17890120,PRCP,0,,,E, +EZE00100082,17890121,TMAX,41,,,E, +EZE00100082,17890121,TMIN,-32,,,E, +ITE00100554,17890121,TMAX,45,,,E, +ITE00100554,17890121,TMIN,16,,,E, +GM000010962,17890121,PRCP,77,,,E, +EZE00100082,17890122,TMAX,24,,,E, +EZE00100082,17890122,TMIN,-31,,,E, +ITE00100554,17890122,TMAX,40,,,E, +ITE00100554,17890122,TMIN,9,,,E, +GM000010962,17890122,PRCP,0,,,E, +EZE00100082,17890123,TMAX,-22,,,E, +EZE00100082,17890123,TMIN,-56,,,E, +ITE00100554,17890123,TMAX,38,,,E, +ITE00100554,17890123,TMIN,0,,,E, +GM000010962,17890123,PRCP,0,,,E, +EZE00100082,17890124,TMAX,13,,,E, +EZE00100082,17890124,TMIN,-29,,,E, +ITE00100554,17890124,TMAX,34,,,E, +ITE00100554,17890124,TMIN,4,,,E, +GM000010962,17890124,PRCP,0,,,E, +EZE00100082,17890125,TMAX,30,,,E, +EZE00100082,17890125,TMIN,3,,,E, +ITE00100554,17890125,TMAX,33,,,E, +ITE00100554,17890125,TMIN,20,,,E, +GM000010962,17890125,PRCP,0,,,E, +EZE00100082,17890126,TMAX,56,,,E, +EZE00100082,17890126,TMIN,28,,,E, +ITE00100554,17890126,TMAX,46,,,E, +ITE00100554,17890126,TMIN,21,,,E, +GM000010962,17890126,PRCP,56,,,E, +EZE00100082,17890127,TMAX,78,,,E, +EZE00100082,17890127,TMIN,28,,,E, +ITE00100554,17890127,TMAX,38,,,E, +ITE00100554,17890127,TMIN,25,,,E, +GM000010962,17890127,PRCP,6,,,E, +EZE00100082,17890128,TMAX,68,,,E, +EZE00100082,17890128,TMIN,39,,,E, +ITE00100554,17890128,TMAX,29,,,E, +ITE00100554,17890128,TMIN,19,,,E, +GM000010962,17890128,PRCP,6,,,E, +EZE00100082,17890129,TMAX,76,,,E, +EZE00100082,17890129,TMIN,-9,,,E, +ITE00100554,17890129,TMAX,19,,,E, +ITE00100554,17890129,TMIN,-4,,,E, +GM000010962,17890129,PRCP,5,,,E, +EZE00100082,17890130,TMAX,5,,,E, +EZE00100082,17890130,TMIN,-25,,,E, +ITE00100554,17890130,TMAX,31,,,E, +ITE00100554,17890130,TMIN,-4,,,E, +GM000010962,17890130,PRCP,0,,,E, +EZE00100082,17890131,TMAX,-2,,,E, +EZE00100082,17890131,TMIN,-37,,,E, +ITE00100554,17890131,TMAX,31,,,E, +ITE00100554,17890131,TMIN,6,,,E, +GM000010962,17890131,PRCP,10,,,E, +EZE00100082,17890201,TMAX,13,,,E, +EZE00100082,17890201,TMIN,-32,,,E, +ITE00100554,17890201,TMAX,31,,,E, +ITE00100554,17890201,TMIN,8,,,E, +GM000010962,17890201,PRCP,8,,,E, +EZE00100082,17890202,TMAX,20,,,E, +EZE00100082,17890202,TMIN,-8,,,E, +ITE00100554,17890202,TMAX,31,,,E, +ITE00100554,17890202,TMIN,8,,,E, +GM000010962,17890202,PRCP,0,,,E, +EZE00100082,17890203,TMAX,62,,,E, +EZE00100082,17890203,TMIN,20,,,E, +ITE00100554,17890203,TMAX,16,,,E, +ITE00100554,17890203,TMIN,4,,,E, +GM000010962,17890203,PRCP,0,,,E, +EZE00100082,17890204,TMAX,71,,,E, +EZE00100082,17890204,TMIN,33,,,E, +ITE00100554,17890204,TMAX,25,,,E, +ITE00100554,17890204,TMIN,8,,,E, +GM000010962,17890204,PRCP,5,,,E, +EZE00100082,17890205,TMAX,72,,,E, +EZE00100082,17890205,TMIN,39,,,E, +ITE00100554,17890205,TMAX,38,,,E, +ITE00100554,17890205,TMIN,4,,,E, +GM000010962,17890205,PRCP,5,,,E, +EZE00100082,17890206,TMAX,46,,,E, +EZE00100082,17890206,TMIN,24,,,E, +ITE00100554,17890206,TMAX,83,,,E, +ITE00100554,17890206,TMIN,40,,,E, +GM000010962,17890206,PRCP,4,,,E, +EZE00100082,17890207,TMAX,48,,,E, +EZE00100082,17890207,TMIN,20,,,E, +ITE00100554,17890207,TMAX,45,,,E, +ITE00100554,17890207,TMIN,9,,,E, +GM000010962,17890207,PRCP,3,,,E, +EZE00100082,17890208,TMAX,44,,,E, +EZE00100082,17890208,TMIN,-1,,,E, +ITE00100554,17890208,TMAX,73,,,E, +ITE00100554,17890208,TMIN,-4,,,E, +GM000010962,17890208,PRCP,29,,,E, +EZE00100082,17890209,TMAX,40,,,E, +EZE00100082,17890209,TMIN,29,,,E, +ITE00100554,17890209,TMAX,45,,,E, +ITE00100554,17890209,TMIN,9,,,E, +GM000010962,17890209,PRCP,16,,,E, +EZE00100082,17890210,TMAX,50,,,E, +EZE00100082,17890210,TMIN,12,,,E, +ITE00100554,17890210,TMAX,38,,,E, +ITE00100554,17890210,TMIN,0,,,E, +GM000010962,17890210,PRCP,6,,,E, +EZE00100082,17890211,TMAX,39,,,E, +EZE00100082,17890211,TMIN,10,,,E, +ITE00100554,17890211,TMAX,31,,,E, +ITE00100554,17890211,TMIN,15,,,E, +GM000010962,17890211,PRCP,29,,,E, +EZE00100082,17890212,TMAX,29,,,E, +EZE00100082,17890212,TMIN,3,,,E, +ITE00100554,17890212,TMAX,63,,,E, +ITE00100554,17890212,TMIN,13,,,E, +GM000010962,17890212,PRCP,28,,,E, +EZE00100082,17890213,TMAX,3,,,E, +EZE00100082,17890213,TMIN,-38,,,E, +ITE00100554,17890213,TMAX,71,,,E, +ITE00100554,17890213,TMIN,6,,,E, +GM000010962,17890213,PRCP,11,,,E, +EZE00100082,17890214,TMAX,60,,,E, +EZE00100082,17890214,TMIN,-6,,,E, +ITE00100554,17890214,TMAX,90,,,E, +ITE00100554,17890214,TMIN,0,,,E, +GM000010962,17890214,PRCP,8,,,E, +EZE00100082,17890215,TMAX,61,,,E, +EZE00100082,17890215,TMIN,39,,,E, +ITE00100554,17890215,TMAX,84,,,E, +ITE00100554,17890215,TMIN,13,,,E, +GM000010962,17890215,PRCP,0,,,E, +EZE00100082,17890216,TMAX,61,,,E, +EZE00100082,17890216,TMIN,20,,,E, +ITE00100554,17890216,TMAX,106,,,E, +ITE00100554,17890216,TMIN,8,,,E, +GM000010962,17890216,PRCP,0,,,E, +EZE00100082,17890217,TMAX,35,,,E, +EZE00100082,17890217,TMIN,14,,,E, +ITE00100554,17890217,TMAX,94,,,E, +ITE00100554,17890217,TMIN,56,,,E, +GM000010962,17890217,PRCP,6,,,E, +EZE00100082,17890218,TMAX,55,,,E, +EZE00100082,17890218,TMIN,12,,,E, +ITE00100554,17890218,TMAX,100,,,E, +ITE00100554,17890218,TMIN,8,,,E, +GM000010962,17890218,PRCP,10,,,E, +EZE00100082,17890219,TMAX,76,,,E, +EZE00100082,17890219,TMIN,53,,,E, +ITE00100554,17890219,TMAX,100,,,E, +ITE00100554,17890219,TMIN,40,,,E, +GM000010962,17890219,PRCP,4,,,E, +EZE00100082,17890220,TMAX,60,,,E, +EZE00100082,17890220,TMIN,22,,,E, +ITE00100554,17890220,TMAX,100,,,E, +ITE00100554,17890220,TMIN,44,,,E, +GM000010962,17890220,PRCP,0,,,E, +EZE00100082,17890221,TMAX,48,,,E, +EZE00100082,17890221,TMIN,20,,,E, +ITE00100554,17890221,TMAX,104,,,E, +ITE00100554,17890221,TMIN,28,,,E, +GM000010962,17890221,PRCP,0,,,E, +EZE00100082,17890222,TMAX,62,,,E, +EZE00100082,17890222,TMIN,15,,,E, +ITE00100554,17890222,TMAX,100,,,E, +ITE00100554,17890222,TMIN,44,,,E, +GM000010962,17890222,PRCP,0,,,E, +EZE00100082,17890223,TMAX,74,,,E, +EZE00100082,17890223,TMIN,22,,,E, +ITE00100554,17890223,TMAX,109,,,E, +ITE00100554,17890223,TMIN,50,,,E, +GM000010962,17890223,PRCP,0,,,E, +EZE00100082,17890224,TMAX,75,,,E, +EZE00100082,17890224,TMIN,42,,,E, +ITE00100554,17890224,TMAX,94,,,E, +ITE00100554,17890224,TMIN,75,,,E, +GM000010962,17890224,PRCP,0,,,E, +EZE00100082,17890225,TMAX,50,,,E, +EZE00100082,17890225,TMIN,15,,,E, +ITE00100554,17890225,TMAX,104,,,E, +ITE00100554,17890225,TMIN,69,,,E, +GM000010962,17890225,PRCP,43,,,E, +EZE00100082,17890226,TMAX,57,,,E, +EZE00100082,17890226,TMIN,15,,,E, +ITE00100554,17890226,TMAX,100,,,E, +ITE00100554,17890226,TMIN,63,,,E, +GM000010962,17890226,PRCP,0,,,E, +EZE00100082,17890227,TMAX,65,,,E, +EZE00100082,17890227,TMIN,28,,,E, +ITE00100554,17890227,TMAX,81,,,E, +ITE00100554,17890227,TMIN,50,,,E, +GM000010962,17890227,PRCP,80,,,E, +EZE00100082,17890228,TMAX,49,,,E, +EZE00100082,17890228,TMIN,20,,,E, +ITE00100554,17890228,TMAX,69,,,E, +ITE00100554,17890228,TMIN,33,,,E, +GM000010962,17890228,PRCP,4,,,E, +EZE00100082,17890301,TMAX,20,,,E, +EZE00100082,17890301,TMIN,-5,,,E, +ITE00100554,17890301,TMAX,53,,,E, +ITE00100554,17890301,TMIN,31,,,E, +GM000010962,17890301,PRCP,12,,,E, +EZE00100082,17890302,TMAX,17,,,E, +EZE00100082,17890302,TMIN,-6,,,E, +ITE00100554,17890302,TMAX,94,,,E, +ITE00100554,17890302,TMIN,56,,,E, +GM000010962,17890302,PRCP,20,,,E, +EZE00100082,17890303,TMAX,6,,,E, +EZE00100082,17890303,TMIN,-10,,,E, +ITE00100554,17890303,TMAX,94,,,E, +ITE00100554,17890303,TMIN,38,,,E, +GM000010962,17890303,PRCP,0,,,E, +EZE00100082,17890304,TMAX,23,,,E, +EZE00100082,17890304,TMIN,-11,,,E, +ITE00100554,17890304,TMAX,44,,,E, +ITE00100554,17890304,TMIN,20,,,E, +GM000010962,17890304,PRCP,17,,,E, +EZE00100082,17890305,TMAX,40,,,E, +EZE00100082,17890305,TMIN,-1,,,E, +ITE00100554,17890305,TMAX,48,,,E, +ITE00100554,17890305,TMIN,23,,,E, +GM000010962,17890305,PRCP,5,,,E, +EZE00100082,17890306,TMAX,38,,,E, +EZE00100082,17890306,TMIN,-8,,,E, +ITE00100554,17890306,TMAX,63,,,E, +ITE00100554,17890306,TMIN,28,,,E, +GM000010962,17890306,PRCP,0,,,E, +EZE00100082,17890307,TMAX,7,,,E, +EZE00100082,17890307,TMIN,-36,,,E, +ITE00100554,17890307,TMAX,69,,,E, +ITE00100554,17890307,TMIN,41,,,E, +GM000010962,17890307,PRCP,0,,,E, +EZE00100082,17890308,TMAX,2,,,E, +EZE00100082,17890308,TMIN,-25,,,E, +ITE00100554,17890308,TMAX,81,,,E, +ITE00100554,17890308,TMIN,46,,,E, +GM000010962,17890308,PRCP,2,,,E, +EZE00100082,17890309,TMAX,2,,,E, +EZE00100082,17890309,TMIN,-41,,,E, +ITE00100554,17890309,TMAX,81,,,E, +ITE00100554,17890309,TMIN,54,,,E, +GM000010962,17890309,PRCP,24,,,E, +EZE00100082,17890310,TMAX,-2,,,E, +EZE00100082,17890310,TMIN,-83,,,E, +ITE00100554,17890310,TMAX,53,,,E, +ITE00100554,17890310,TMIN,20,,,E, +GM000010962,17890310,PRCP,6,,,E, +EZE00100082,17890311,TMAX,-4,,,E, +EZE00100082,17890311,TMIN,-66,,,E, +ITE00100554,17890311,TMAX,48,,,E, +ITE00100554,17890311,TMIN,-3,,,E, +GM000010962,17890311,PRCP,0,,,E, +EZE00100082,17890312,TMAX,-32,,,E, +EZE00100082,17890312,TMIN,-109,,,E, +ITE00100554,17890312,TMAX,53,,,E, +ITE00100554,17890312,TMIN,13,,,E, +GM000010962,17890312,PRCP,0,,,E, +EZE00100082,17890313,TMAX,-16,,,E, +EZE00100082,17890313,TMIN,-88,,,E, +ITE00100554,17890313,TMAX,78,,,E, +ITE00100554,17890313,TMIN,-13,,,E, +GM000010962,17890313,PRCP,0,,,E, +EZE00100082,17890314,TMAX,38,,,E, +EZE00100082,17890314,TMIN,-40,,,E, +ITE00100554,17890314,TMAX,41,,,E, +ITE00100554,17890314,TMIN,20,,,E, +GM000010962,17890314,PRCP,0,,,E, +EZE00100082,17890315,TMAX,52,,,E, +EZE00100082,17890315,TMIN,-4,,,E, +ITE00100554,17890315,TMAX,29,,,E, +ITE00100554,17890315,TMIN,13,,,E, +GM000010962,17890315,PRCP,0,,,E, +EZE00100082,17890316,TMAX,31,,,E, +EZE00100082,17890316,TMIN,8,,,E, +ITE00100554,17890316,TMAX,91,,,E, +ITE00100554,17890316,TMIN,28,,,E, +GM000010962,17890316,PRCP,10,,,E, +EZE00100082,17890317,TMAX,26,,,E, +EZE00100082,17890317,TMIN,-8,,,E, +ITE00100554,17890317,TMAX,88,,,E, +ITE00100554,17890317,TMIN,53,,,E, +GM000010962,17890317,PRCP,3,,,E, +EZE00100082,17890318,TMAX,15,,,E, +EZE00100082,17890318,TMIN,-7,,,E, +ITE00100554,17890318,TMAX,103,,,E, +ITE00100554,17890318,TMIN,69,,,E, +GM000010962,17890318,PRCP,4,,,E, +EZE00100082,17890319,TMAX,14,,,E, +EZE00100082,17890319,TMIN,-10,,,E, +ITE00100554,17890319,TMAX,100,,,E, +ITE00100554,17890319,TMIN,56,,,E, +GM000010962,17890319,PRCP,0,,,E, +EZE00100082,17890320,TMAX,9,,,E, +EZE00100082,17890320,TMIN,-22,,,E, +ITE00100554,17890320,TMAX,90,,,E, +ITE00100554,17890320,TMIN,50,,,E, +GM000010962,17890320,PRCP,10,,,E, +EZE00100082,17890321,TMAX,38,,,E, +EZE00100082,17890321,TMIN,-28,,,E, +ITE00100554,17890321,TMAX,104,,,E, +ITE00100554,17890321,TMIN,34,,,E, +GM000010962,17890321,PRCP,16,,,E, +EZE00100082,17890322,TMAX,63,,,E, +EZE00100082,17890322,TMIN,18,,,E, +ITE00100554,17890322,TMAX,128,,,E, +ITE00100554,17890322,TMIN,44,,,E, +GM000010962,17890322,PRCP,51,,,E, +EZE00100082,17890323,TMAX,84,,,E, +EZE00100082,17890323,TMIN,35,,,E, +ITE00100554,17890323,TMAX,125,,,E, +ITE00100554,17890323,TMIN,78,,,E, +GM000010962,17890323,PRCP,3,,,E, +EZE00100082,17890324,TMAX,50,,,E, +EZE00100082,17890324,TMIN,-2,,,E, +ITE00100554,17890324,TMAX,150,,,E, +ITE00100554,17890324,TMIN,56,,,E, +GM000010962,17890324,PRCP,19,,,E, +EZE00100082,17890325,TMAX,45,,,E, +EZE00100082,17890325,TMIN,-8,,,E, +ITE00100554,17890325,TMAX,100,,,E, +ITE00100554,17890325,TMIN,75,,,E, +GM000010962,17890325,PRCP,6,,,E, +EZE00100082,17890326,TMAX,63,,,E, +EZE00100082,17890326,TMIN,16,,,E, +ITE00100554,17890326,TMAX,106,,,E, +ITE00100554,17890326,TMIN,66,,,E, +GM000010962,17890326,PRCP,32,,,E, +EZE00100082,17890327,TMAX,30,,,E, +EZE00100082,17890327,TMIN,-30,,,E, +ITE00100554,17890327,TMAX,104,,,E, +ITE00100554,17890327,TMIN,69,,,E, +GM000010962,17890327,PRCP,17,,,E, +EZE00100082,17890328,TMAX,11,,,E, +EZE00100082,17890328,TMIN,-33,,,E, +ITE00100554,17890328,TMAX,90,,,E, +ITE00100554,17890328,TMIN,16,,,E, +GM000010962,17890328,PRCP,15,,,E, +EZE00100082,17890329,TMAX,35,,,E, +EZE00100082,17890329,TMIN,-18,,,E, +ITE00100554,17890329,TMAX,25,,,E, +ITE00100554,17890329,TMIN,13,,,E, +GM000010962,17890329,PRCP,4,,,E, +EZE00100082,17890330,TMAX,31,,,E, +EZE00100082,17890330,TMIN,-26,,,E, +ITE00100554,17890330,TMAX,75,,,E, +ITE00100554,17890330,TMIN,25,,,E, +GM000010962,17890330,PRCP,0,,,E, +EZE00100082,17890331,TMAX,25,,,E, +EZE00100082,17890331,TMIN,-32,,,E, +ITE00100554,17890331,TMAX,104,,,E, +ITE00100554,17890331,TMIN,16,,,E, +GM000010962,17890331,PRCP,0,,,E, +EZE00100082,17890401,TMAX,55,,,E, +EZE00100082,17890401,TMIN,-2,,,E, +ITE00100554,17890401,TMAX,113,,,E, +ITE00100554,17890401,TMIN,25,,,E, +GM000010962,17890401,PRCP,6,,,E, +EZE00100082,17890402,TMAX,99,,,E, +EZE00100082,17890402,TMIN,27,,,E, +ITE00100554,17890402,TMAX,106,,,E, +ITE00100554,17890402,TMIN,46,,,E, +GM000010962,17890402,PRCP,19,,,E, +EZE00100082,17890403,TMAX,141,,,E, +EZE00100082,17890403,TMIN,84,,,E, +ITE00100554,17890403,TMAX,106,,,E, +ITE00100554,17890403,TMIN,94,,,E, +GM000010962,17890403,PRCP,0,,,E, +EZE00100082,17890404,TMAX,185,,,E, +EZE00100082,17890404,TMIN,83,,,E, +ITE00100554,17890404,TMAX,148,,,E, +ITE00100554,17890404,TMIN,91,,,E, +GM000010962,17890404,PRCP,0,,,E, +EZE00100082,17890405,TMAX,112,,,E, +EZE00100082,17890405,TMIN,70,,,E, +ITE00100554,17890405,TMAX,154,,,E, +ITE00100554,17890405,TMIN,73,,,E, +GM000010962,17890405,PRCP,0,,,E, +EZE00100082,17890406,TMAX,105,,,E, +EZE00100082,17890406,TMIN,58,,,E, +ITE00100554,17890406,TMAX,163,,,E, +ITE00100554,17890406,TMIN,91,,,E, +GM000010962,17890406,PRCP,0,,,E, +EZE00100082,17890407,TMAX,130,,,E, +EZE00100082,17890407,TMIN,45,,,E, +ITE00100554,17890407,TMAX,188,,,E, +ITE00100554,17890407,TMIN,104,,,E, +GM000010962,17890407,PRCP,0,,,E, +EZE00100082,17890408,TMAX,164,,,E, +EZE00100082,17890408,TMIN,73,,,E, +ITE00100554,17890408,TMAX,191,,,E, +ITE00100554,17890408,TMIN,131,,,E, +GM000010962,17890408,PRCP,0,,,E, +EZE00100082,17890409,TMAX,182,,,E, +EZE00100082,17890409,TMIN,87,,,E, +ITE00100554,17890409,TMAX,169,,,E, +ITE00100554,17890409,TMIN,104,,,E, +GM000010962,17890409,PRCP,0,,,E, +EZE00100082,17890410,TMAX,164,,,E, +EZE00100082,17890410,TMIN,71,,,E, +ITE00100554,17890410,TMAX,175,,,E, +ITE00100554,17890410,TMIN,106,,,E, +GM000010962,17890410,PRCP,0,,,E, +EZE00100082,17890411,TMAX,189,,,E, +EZE00100082,17890411,TMIN,70,,,E, +ITE00100554,17890411,TMAX,188,,,E, +ITE00100554,17890411,TMIN,125,,,E, +GM000010962,17890411,PRCP,7,,,E, +EZE00100082,17890412,TMAX,189,,,E, +EZE00100082,17890412,TMIN,93,,,E, +ITE00100554,17890412,TMAX,194,,,E, +ITE00100554,17890412,TMIN,119,,,E, +GM000010962,17890412,PRCP,0,,,E, +EZE00100082,17890413,TMAX,155,,,E, +EZE00100082,17890413,TMIN,47,,,E, +ITE00100554,17890413,TMAX,181,,,E, +ITE00100554,17890413,TMIN,125,,,E, +GM000010962,17890413,PRCP,0,,,E, +EZE00100082,17890414,TMAX,85,,,E, +EZE00100082,17890414,TMIN,38,,,E, +ITE00100554,17890414,TMAX,181,,,E, +ITE00100554,17890414,TMIN,138,,,E, +GM000010962,17890414,PRCP,38,,,E, +EZE00100082,17890415,TMAX,110,,,E, +EZE00100082,17890415,TMIN,33,,,E, +ITE00100554,17890415,TMAX,175,,,E, +ITE00100554,17890415,TMIN,133,,,E, +GM000010962,17890415,PRCP,0,,,E, +EZE00100082,17890416,TMAX,135,,,E, +EZE00100082,17890416,TMIN,47,,,E, +ITE00100554,17890416,TMAX,191,,,E, +ITE00100554,17890416,TMIN,133,,,E, +GM000010962,17890416,PRCP,0,,,E, +EZE00100082,17890417,TMAX,136,,,E, +EZE00100082,17890417,TMIN,35,,,E, +ITE00100554,17890417,TMAX,179,,,E, +ITE00100554,17890417,TMIN,133,,,E, +GM000010962,17890417,PRCP,0,,,E, +EZE00100082,17890418,TMAX,164,,,E, +EZE00100082,17890418,TMIN,57,,,E, +ITE00100554,17890418,TMAX,188,,,E, +ITE00100554,17890418,TMIN,131,,,E, +GM000010962,17890418,PRCP,0,,,E, +EZE00100082,17890419,TMAX,171,,,E, +EZE00100082,17890419,TMIN,80,,,E, +ITE00100554,17890419,TMAX,194,,,E, +ITE00100554,17890419,TMIN,150,,,E, +GM000010962,17890419,PRCP,0,,,E, +EZE00100082,17890420,TMAX,127,,,E, +EZE00100082,17890420,TMIN,99,,,E, +ITE00100554,17890420,TMAX,181,,,E, +ITE00100554,17890420,TMIN,138,,,E, +GM000010962,17890420,PRCP,4,,,E, +EZE00100082,17890421,TMAX,132,,,E, +EZE00100082,17890421,TMIN,97,,,E, +ITE00100554,17890421,TMAX,195,,,E, +ITE00100554,17890421,TMIN,121,,,E, +GM000010962,17890421,PRCP,17,,,E, +EZE00100082,17890422,TMAX,162,,,E, +EZE00100082,17890422,TMIN,102,,,E, +ITE00100554,17890422,TMAX,204,,,E, +ITE00100554,17890422,TMIN,138,,,E, +GM000010962,17890422,PRCP,0,,,E, +EZE00100082,17890423,TMAX,165,,,E, +EZE00100082,17890423,TMIN,98,,,E, +ITE00100554,17890423,TMAX,200,,,E, +ITE00100554,17890423,TMIN,131,,,E, +GM000010962,17890423,PRCP,2,,,E, +EZE00100082,17890424,TMAX,136,,,E, +EZE00100082,17890424,TMIN,90,,,E, +ITE00100554,17890424,TMAX,200,,,E, +ITE00100554,17890424,TMIN,153,,,E, +GM000010962,17890424,PRCP,9,,,E, +EZE00100082,17890425,TMAX,119,,,E, +EZE00100082,17890425,TMIN,48,,,E, +ITE00100554,17890425,TMAX,181,,,E, +ITE00100554,17890425,TMIN,106,,,E, +GM000010962,17890425,PRCP,9,,,E, +EZE00100082,17890426,TMAX,145,,,E, +EZE00100082,17890426,TMIN,45,,,E, +ITE00100554,17890426,TMAX,156,,,E, +ITE00100554,17890426,TMIN,100,,,E, +GM000010962,17890426,PRCP,5,,,E, +EZE00100082,17890427,TMAX,150,,,E, +EZE00100082,17890427,TMIN,97,,,E, +ITE00100554,17890427,TMAX,131,,,E, +ITE00100554,17890427,TMIN,119,,,E, +GM000010962,17890427,PRCP,0,,,E, +EZE00100082,17890428,TMAX,209,,,E, +EZE00100082,17890428,TMIN,102,,,E, +ITE00100554,17890428,TMAX,138,,,E, +ITE00100554,17890428,TMIN,133,,,E, +GM000010962,17890428,PRCP,0,,,E, +EZE00100082,17890429,TMAX,247,,,E, +EZE00100082,17890429,TMIN,104,,,E, +ITE00100554,17890429,TMAX,181,,,E, +ITE00100554,17890429,TMIN,134,,,E, +GM000010962,17890429,PRCP,0,,,E, +EZE00100082,17890430,TMAX,272,,,E, +EZE00100082,17890430,TMIN,140,,,E, +ITE00100554,17890430,TMAX,181,,,E, +ITE00100554,17890430,TMIN,138,,,E, +GM000010962,17890430,PRCP,0,,,E, +EZE00100082,17890501,TMAX,210,,,E, +EZE00100082,17890501,TMIN,136,,,E, +ITE00100554,17890501,TMAX,188,,,E, +ITE00100554,17890501,TMIN,104,,,E, +GM000010962,17890501,PRCP,0,,,E, +EZE00100082,17890502,TMAX,254,,,E, +EZE00100082,17890502,TMIN,130,,,E, +ITE00100554,17890502,TMAX,201,,,E, +ITE00100554,17890502,TMIN,131,,,E, +GM000010962,17890502,PRCP,0,,,E, +EZE00100082,17890503,TMAX,246,,,E, +EZE00100082,17890503,TMIN,127,,,E, +ITE00100554,17890503,TMAX,213,,,E, +ITE00100554,17890503,TMIN,131,,,E, +GM000010962,17890503,PRCP,0,,,E, +EZE00100082,17890504,TMAX,274,,,E, +EZE00100082,17890504,TMIN,151,,,E, +ITE00100554,17890504,TMAX,213,,,E, +ITE00100554,17890504,TMIN,128,,,E, +GM000010962,17890504,PRCP,0,,,E, +EZE00100082,17890505,TMAX,242,,,E, +EZE00100082,17890505,TMIN,169,,,E, +ITE00100554,17890505,TMAX,210,,,E, +ITE00100554,17890505,TMIN,150,,,E, +GM000010962,17890505,PRCP,0,,,E, +EZE00100082,17890506,TMAX,247,,,E, +EZE00100082,17890506,TMIN,162,,,E, +ITE00100554,17890506,TMAX,238,,,E, +ITE00100554,17890506,TMIN,150,,,E, +GM000010962,17890506,PRCP,8,,,E, +EZE00100082,17890507,TMAX,183,,,E, +EZE00100082,17890507,TMIN,125,,,E, +ITE00100554,17890507,TMAX,250,,,E, +ITE00100554,17890507,TMIN,163,,,E, +GM000010962,17890507,PRCP,221,,,E, +EZE00100082,17890508,TMAX,168,,,E, +EZE00100082,17890508,TMIN,102,,,E, +ITE00100554,17890508,TMAX,244,,,E, +ITE00100554,17890508,TMIN,159,,,E, +GM000010962,17890508,PRCP,5,,,E, +EZE00100082,17890509,TMAX,234,,,E, +EZE00100082,17890509,TMIN,140,,,E, +ITE00100554,17890509,TMAX,225,,,E, +ITE00100554,17890509,TMIN,175,,,E, +GM000010962,17890509,PRCP,0,,,E, +EZE00100082,17890510,TMAX,252,,,E, +EZE00100082,17890510,TMIN,154,,,E, +ITE00100554,17890510,TMAX,250,,,E, +ITE00100554,17890510,TMIN,163,,,E, +GM000010962,17890510,PRCP,2,,,E, +EZE00100082,17890511,TMAX,257,,,E, +EZE00100082,17890511,TMIN,148,,,E, +ITE00100554,17890511,TMAX,263,,,E, +ITE00100554,17890511,TMIN,175,,,E, +GM000010962,17890511,PRCP,4,,,E, +EZE00100082,17890512,TMAX,255,,,E, +EZE00100082,17890512,TMIN,152,,,E, +ITE00100554,17890512,TMAX,263,,,E, +ITE00100554,17890512,TMIN,175,,,E, +GM000010962,17890512,PRCP,0,,,E, +EZE00100082,17890513,TMAX,262,,,E, +EZE00100082,17890513,TMIN,169,,,E, +ITE00100554,17890513,TMAX,265,,,E, +ITE00100554,17890513,TMIN,188,,,E, +GM000010962,17890513,PRCP,0,,,E, +EZE00100082,17890514,TMAX,276,,,E, +EZE00100082,17890514,TMIN,152,,,E, +ITE00100554,17890514,TMAX,275,,,E, +ITE00100554,17890514,TMIN,181,,,E, +GM000010962,17890514,PRCP,1,,,E, +EZE00100082,17890515,TMAX,291,,,E, +EZE00100082,17890515,TMIN,172,,,E, +ITE00100554,17890515,TMAX,229,,,E, +ITE00100554,17890515,TMIN,169,,,E, +GM000010962,17890515,PRCP,161,,,E, +EZE00100082,17890516,TMAX,208,,,E, +EZE00100082,17890516,TMIN,165,,,E, +ITE00100554,17890516,TMAX,256,,,E, +ITE00100554,17890516,TMIN,169,,,E, +GM000010962,17890516,PRCP,48,,,E, +EZE00100082,17890517,TMAX,203,,,E, +EZE00100082,17890517,TMIN,141,,,E, +ITE00100554,17890517,TMAX,253,,,E, +ITE00100554,17890517,TMIN,175,,,E, +GM000010962,17890517,PRCP,8,,,E, +EZE00100082,17890518,TMAX,212,,,E, +EZE00100082,17890518,TMIN,132,,,E, +ITE00100554,17890518,TMAX,263,,,E, +ITE00100554,17890518,TMIN,181,,,E, +GM000010962,17890518,PRCP,0,,,E, +EZE00100082,17890519,TMAX,152,,,E, +EZE00100082,17890519,TMIN,121,,,E, +ITE00100554,17890519,TMAX,263,,,E, +ITE00100554,17890519,TMIN,181,,,E, +GM000010962,17890519,PRCP,2,,,E, +EZE00100082,17890520,TMAX,155,,,E, +EZE00100082,17890520,TMIN,94,,,E, +ITE00100554,17890520,TMAX,241,,,E, +ITE00100554,17890520,TMIN,191,,,E, +GM000010962,17890520,PRCP,0,,,E, +EZE00100082,17890521,TMAX,175,,,E, +EZE00100082,17890521,TMIN,83,,,E, +ITE00100554,17890521,TMAX,241,,,E, +ITE00100554,17890521,TMIN,179,,,E, +GM000010962,17890521,PRCP,0,,,E, +EZE00100082,17890522,TMAX,178,,,E, +EZE00100082,17890522,TMIN,129,,,E, +ITE00100554,17890522,TMAX,259,,,E, +ITE00100554,17890522,TMIN,169,,,E, +GM000010962,17890522,PRCP,283,,,E, +EZE00100082,17890523,TMAX,205,,,E, +EZE00100082,17890523,TMIN,127,,,E, +ITE00100554,17890523,TMAX,244,,,E, +ITE00100554,17890523,TMIN,181,,,E, +GM000010962,17890523,PRCP,9,,,E, +EZE00100082,17890524,TMAX,225,,,E, +EZE00100082,17890524,TMIN,138,,,E, +ITE00100554,17890524,TMAX,271,,,E, +ITE00100554,17890524,TMIN,188,,,E, +GM000010962,17890524,PRCP,0,,,E, +EZE00100082,17890525,TMAX,238,,,E, +EZE00100082,17890525,TMIN,137,,,E, +ITE00100554,17890525,TMAX,206,,,E, +ITE00100554,17890525,TMIN,169,,,E, +GM000010962,17890525,PRCP,0,,,E, +EZE00100082,17890526,TMAX,222,,,E, +EZE00100082,17890526,TMIN,168,,,E, +ITE00100554,17890526,TMAX,208,,,E, +ITE00100554,17890526,TMIN,163,,,E, +GM000010962,17890526,PRCP,272,,,E, +EZE00100082,17890527,TMAX,244,,,E, +EZE00100082,17890527,TMIN,166,,,E, +ITE00100554,17890527,TMAX,220,,,E, +ITE00100554,17890527,TMIN,158,,,E, +GM000010962,17890527,PRCP,0,,,E, +EZE00100082,17890528,TMAX,265,,,E, +EZE00100082,17890528,TMIN,179,,,E, +ITE00100554,17890528,TMAX,226,,,E, +ITE00100554,17890528,TMIN,150,,,E, +GM000010962,17890528,PRCP,24,,,E, +EZE00100082,17890529,TMAX,270,,,E, +EZE00100082,17890529,TMIN,162,,,E, +ITE00100554,17890529,TMAX,231,,,E, +ITE00100554,17890529,TMIN,156,,,E, +GM000010962,17890529,PRCP,90,,,E, +EZE00100082,17890530,TMAX,296,,,E, +EZE00100082,17890530,TMIN,170,,,E, +ITE00100554,17890530,TMAX,231,,,E, +ITE00100554,17890530,TMIN,179,,,E, +GM000010962,17890530,PRCP,62,,,E, +EZE00100082,17890531,TMAX,261,,,E, +EZE00100082,17890531,TMIN,148,,,E, +ITE00100554,17890531,TMAX,229,,,E, +ITE00100554,17890531,TMIN,175,,,E, +GM000010962,17890531,PRCP,0,,,E, +EZE00100082,17890601,TMAX,274,,,E, +EZE00100082,17890601,TMIN,168,,,E, +ITE00100554,17890601,TMAX,225,,,E, +ITE00100554,17890601,TMIN,191,,,E, +GM000010962,17890601,PRCP,112,,,E, +EZE00100082,17890602,TMAX,283,,,E, +EZE00100082,17890602,TMIN,180,,,E, +ITE00100554,17890602,TMAX,213,,,E, +ITE00100554,17890602,TMIN,188,,,E, +GM000010962,17890602,PRCP,0,,,E, +EZE00100082,17890603,TMAX,241,,,E, +EZE00100082,17890603,TMIN,162,,,E, +ITE00100554,17890603,TMAX,188,,,E, +ITE00100554,17890603,TMIN,125,,,E, +GM000010962,17890603,PRCP,5,,,E, +EZE00100082,17890604,TMAX,247,,,E, +EZE00100082,17890604,TMIN,130,,,E, +ITE00100554,17890604,TMAX,181,,,E, +ITE00100554,17890604,TMIN,125,,,E, +GM000010962,17890604,PRCP,0,,,E, +EZE00100082,17890605,TMAX,167,,,E, +EZE00100082,17890605,TMIN,129,,,E, +ITE00100554,17890605,TMAX,198,,,E, +ITE00100554,17890605,TMIN,116,,,E, +GM000010962,17890605,PRCP,100,,,E, +EZE00100082,17890606,TMAX,144,,,E, +EZE00100082,17890606,TMIN,124,,,E, +ITE00100554,17890606,TMAX,213,,,E, +ITE00100554,17890606,TMIN,121,,,E, +GM000010962,17890606,PRCP,60,,,E, +EZE00100082,17890607,TMAX,175,,,E, +EZE00100082,17890607,TMIN,121,,,E, +ITE00100554,17890607,TMAX,213,,,E, +ITE00100554,17890607,TMIN,123,,,E, +GM000010962,17890607,PRCP,20,,,E, +EZE00100082,17890608,TMAX,193,,,E, +EZE00100082,17890608,TMIN,113,,,E, +ITE00100554,17890608,TMAX,234,,,E, +ITE00100554,17890608,TMIN,160,,,E, +GM000010962,17890608,PRCP,21,,,E, +EZE00100082,17890609,TMAX,196,,,E, +EZE00100082,17890609,TMIN,123,,,E, +ITE00100554,17890609,TMAX,219,,,E, +ITE00100554,17890609,TMIN,134,,,E, +GM000010962,17890609,PRCP,52,,,E, +EZE00100082,17890610,TMAX,193,,,E, +EZE00100082,17890610,TMIN,128,,,E, +ITE00100554,17890610,TMAX,240,,,E, +ITE00100554,17890610,TMIN,141,,,E, +GM000010962,17890610,PRCP,19,,,E, +EZE00100082,17890611,TMAX,193,,,E, +EZE00100082,17890611,TMIN,132,,,E, +ITE00100554,17890611,TMAX,213,,,E, +ITE00100554,17890611,TMIN,150,,,E, +GM000010962,17890611,PRCP,47,,,E, +EZE00100082,17890612,TMAX,213,,,E, +EZE00100082,17890612,TMIN,128,,,E, +ITE00100554,17890612,TMAX,220,,,E, +ITE00100554,17890612,TMIN,145,,,E, +GM000010962,17890612,PRCP,93,,,E, +EZE00100082,17890613,TMAX,167,,,E, +EZE00100082,17890613,TMIN,135,,,E, +ITE00100554,17890613,TMAX,219,,,E, +ITE00100554,17890613,TMIN,150,,,E, +GM000010962,17890613,PRCP,14,,,E, +EZE00100082,17890614,TMAX,213,,,E, +EZE00100082,17890614,TMIN,143,,,E, +ITE00100554,17890614,TMAX,208,,,E, +ITE00100554,17890614,TMIN,150,,,E, +GM000010962,17890614,PRCP,0,,,E, +EZE00100082,17890615,TMAX,231,,,E, +EZE00100082,17890615,TMIN,126,,,E, +ITE00100554,17890615,TMAX,225,,,E, +ITE00100554,17890615,TMIN,150,,,E, +GM000010962,17890615,PRCP,24,,,E, +EZE00100082,17890616,TMAX,252,,,E, +EZE00100082,17890616,TMIN,151,,,E, +ITE00100554,17890616,TMAX,250,,,E, +ITE00100554,17890616,TMIN,181,,,E, +GM000010962,17890616,PRCP,0,,,E, +EZE00100082,17890617,TMAX,270,,,E, +EZE00100082,17890617,TMIN,161,,,E, +ITE00100554,17890617,TMAX,234,,,E, +ITE00100554,17890617,TMIN,181,,,E, +GM000010962,17890617,PRCP,55,,,E, +EZE00100082,17890618,TMAX,284,,,E, +EZE00100082,17890618,TMIN,175,,,E, +ITE00100554,17890618,TMAX,258,,,E, +ITE00100554,17890618,TMIN,175,,,E, +GM000010962,17890618,PRCP,3,,,E, +EZE00100082,17890619,TMAX,276,,,E, +EZE00100082,17890619,TMIN,181,,,E, +ITE00100554,17890619,TMAX,278,,,E, +ITE00100554,17890619,TMIN,194,,,E, +GM000010962,17890619,PRCP,0,,,E, +EZE00100082,17890620,TMAX,302,,,E, +EZE00100082,17890620,TMIN,174,,,E, +ITE00100554,17890620,TMAX,291,,,E, +ITE00100554,17890620,TMIN,215,,,E, +GM000010962,17890620,PRCP,18,,,E, +EZE00100082,17890621,TMAX,297,,,E, +EZE00100082,17890621,TMIN,177,,,E, +ITE00100554,17890621,TMAX,281,,,E, +ITE00100554,17890621,TMIN,203,,,E, +GM000010962,17890621,PRCP,5,,,E, +EZE00100082,17890622,TMAX,247,,,E, +EZE00100082,17890622,TMIN,170,,,E, +ITE00100554,17890622,TMAX,256,,,E, +ITE00100554,17890622,TMIN,206,,,E, +GM000010962,17890622,PRCP,68,,,E, +EZE00100082,17890623,TMAX,219,,,E, +EZE00100082,17890623,TMIN,160,,,E, +ITE00100554,17890623,TMAX,263,,,E, +ITE00100554,17890623,TMIN,191,,,E, +GM000010962,17890623,PRCP,81,,,E, +EZE00100082,17890624,TMAX,283,,,E, +EZE00100082,17890624,TMIN,140,,,E, +ITE00100554,17890624,TMAX,269,,,E, +ITE00100554,17890624,TMIN,184,,,E, +GM000010962,17890624,PRCP,0,,,E, +EZE00100082,17890625,TMAX,240,,,E, +EZE00100082,17890625,TMIN,122,,,E, +ITE00100554,17890625,TMAX,263,,,E, +ITE00100554,17890625,TMIN,188,,,E, +GM000010962,17890625,PRCP,49,,,E, +EZE00100082,17890626,TMAX,230,,,E, +EZE00100082,17890626,TMIN,122,,,E, +ITE00100554,17890626,TMAX,269,,,E, +ITE00100554,17890626,TMIN,188,,,E, +GM000010962,17890626,PRCP,0,,,E, +EZE00100082,17890627,TMAX,170,,,E, +EZE00100082,17890627,TMIN,134,,,E, +ITE00100554,17890627,TMAX,275,,,E, +ITE00100554,17890627,TMIN,190,,,E, +GM000010962,17890627,PRCP,18,,,E, +EZE00100082,17890628,TMAX,211,,,E, +EZE00100082,17890628,TMIN,121,,,E, +ITE00100554,17890628,TMAX,263,,,E, +ITE00100554,17890628,TMIN,194,,,E, +GM000010962,17890628,PRCP,9,,,E, +EZE00100082,17890629,TMAX,195,,,E, +EZE00100082,17890629,TMIN,120,,,E, +ITE00100554,17890629,TMAX,223,,,E, +ITE00100554,17890629,TMIN,194,,,E, +GM000010962,17890629,PRCP,24,,,E, +EZE00100082,17890630,TMAX,185,,,E, +EZE00100082,17890630,TMIN,105,,,E, +ITE00100554,17890630,TMAX,231,,,E, +ITE00100554,17890630,TMIN,150,,,E, +GM000010962,17890630,PRCP,82,,,E, +EZE00100082,17890701,TMAX,150,,,E, +EZE00100082,17890701,TMIN,136,,,E, +ITE00100554,17890701,TMAX,231,,,E, +ITE00100554,17890701,TMIN,150,,,E, +GM000010962,17890701,PRCP,44,,,E, +EZE00100082,17890702,TMAX,187,,,E, +EZE00100082,17890702,TMIN,136,,,E, +ITE00100554,17890702,TMAX,263,,,E, +ITE00100554,17890702,TMIN,158,,,E, +GM000010962,17890702,PRCP,17,,,E, +EZE00100082,17890703,TMAX,220,,,E, +EZE00100082,17890703,TMIN,145,,,E, +ITE00100554,17890703,TMAX,263,,,E, +ITE00100554,17890703,TMIN,165,,,E, +GM000010962,17890703,PRCP,0,,,E, +EZE00100082,17890704,TMAX,245,,,E, +EZE00100082,17890704,TMIN,160,,,E, +ITE00100554,17890704,TMAX,273,,,E, +ITE00100554,17890704,TMIN,223,,,E, +GM000010962,17890704,PRCP,0,,,E, +EZE00100082,17890705,TMAX,292,,,E, +EZE00100082,17890705,TMIN,152,,,E, +ITE00100554,17890705,TMAX,295,,,E, +ITE00100554,17890705,TMIN,190,,,E, +GM000010962,17890705,PRCP,0,,,E, +EZE00100082,17890706,TMAX,282,,,E, +EZE00100082,17890706,TMIN,184,,,E, +ITE00100554,17890706,TMAX,294,,,E, +ITE00100554,17890706,TMIN,194,,,E, +GM000010962,17890706,PRCP,0,,,E, +EZE00100082,17890707,TMAX,220,,,E, +EZE00100082,17890707,TMIN,176,,,E, +ITE00100554,17890707,TMAX,281,,,E, +ITE00100554,17890707,TMIN,195,,,E, +GM000010962,17890707,PRCP,48,,,E, +EZE00100082,17890708,TMAX,255,,,E, +EZE00100082,17890708,TMIN,170,,,E, +ITE00100554,17890708,TMAX,278,,,E, +ITE00100554,17890708,TMIN,223,,,E, +GM000010962,17890708,PRCP,0,,,E, +EZE00100082,17890709,TMAX,246,,,E, +EZE00100082,17890709,TMIN,164,,,E, +ITE00100554,17890709,TMAX,304,,,E, +ITE00100554,17890709,TMIN,208,,,E, +GM000010962,17890709,PRCP,0,,,E, +EZE00100082,17890710,TMAX,297,,,E, +EZE00100082,17890710,TMIN,173,,,E, +ITE00100554,17890710,TMAX,315,,,E, +ITE00100554,17890710,TMIN,213,,,E, +GM000010962,17890710,PRCP,0,,,E, +EZE00100082,17890711,TMAX,274,,,E, +EZE00100082,17890711,TMIN,193,,,E, +ITE00100554,17890711,TMAX,319,,,E, +ITE00100554,17890711,TMIN,229,,,E, +GM000010962,17890711,PRCP,2,,,E, +EZE00100082,17890712,TMAX,276,,,E, +EZE00100082,17890712,TMIN,190,,,E, +ITE00100554,17890712,TMAX,306,,,E, +ITE00100554,17890712,TMIN,219,,,E, +GM000010962,17890712,PRCP,4,,,E, +EZE00100082,17890713,TMAX,317,,,E, +EZE00100082,17890713,TMIN,199,,,E, +ITE00100554,17890713,TMAX,294,,,E, +ITE00100554,17890713,TMIN,225,,,E, +GM000010962,17890713,PRCP,68,,,E, +EZE00100082,17890714,TMAX,246,,,E, +EZE00100082,17890714,TMIN,198,,,E, +ITE00100554,17890714,TMAX,275,,,E, +ITE00100554,17890714,TMIN,231,,,E, +GM000010962,17890714,PRCP,86,,,E, +EZE00100082,17890715,TMAX,262,,,E, +EZE00100082,17890715,TMIN,192,,,E, +ITE00100554,17890715,TMAX,281,,,E, +ITE00100554,17890715,TMIN,191,,,E, +GM000010962,17890715,PRCP,0,,,E, +EZE00100082,17890716,TMAX,294,,,E, +EZE00100082,17890716,TMIN,181,,,E, +ITE00100554,17890716,TMAX,294,,,E, +ITE00100554,17890716,TMIN,209,,,E, +GM000010962,17890716,PRCP,0,,,E, +EZE00100082,17890717,TMAX,309,,,E, +EZE00100082,17890717,TMIN,195,,,E, +ITE00100554,17890717,TMAX,294,,,E, +ITE00100554,17890717,TMIN,219,,,E, +GM000010962,17890717,PRCP,4,,,E, +EZE00100082,17890718,TMAX,262,,,E, +EZE00100082,17890718,TMIN,188,,,E, +ITE00100554,17890718,TMAX,294,,,E, +ITE00100554,17890718,TMIN,204,,,E, +GM000010962,17890718,PRCP,47,,,E, +EZE00100082,17890719,TMAX,195,,,E, +EZE00100082,17890719,TMIN,134,,,E, +ITE00100554,17890719,TMAX,271,,,E, +ITE00100554,17890719,TMIN,181,,,E, +GM000010962,17890719,PRCP,262,,,E, +EZE00100082,17890720,TMAX,230,,,E, +EZE00100082,17890720,TMIN,134,,,E, +ITE00100554,17890720,TMAX,283,,,E, +ITE00100554,17890720,TMIN,206,,,E, +GM000010962,17890720,PRCP,6,,,E, +EZE00100082,17890721,TMAX,205,,,E, +EZE00100082,17890721,TMIN,162,,,E, +ITE00100554,17890721,TMAX,294,,,E, +ITE00100554,17890721,TMIN,206,,,E, +GM000010962,17890721,PRCP,3,,,E, +EZE00100082,17890722,TMAX,237,,,E, +EZE00100082,17890722,TMIN,160,,,E, +ITE00100554,17890722,TMAX,288,,,E, +ITE00100554,17890722,TMIN,225,,,E, +GM000010962,17890722,PRCP,4,,,E, +EZE00100082,17890723,TMAX,251,,,E, +EZE00100082,17890723,TMIN,185,,,E, +ITE00100554,17890723,TMAX,244,,,E, +ITE00100554,17890723,TMIN,204,,,E, +GM000010962,17890723,PRCP,202,,,E, +EZE00100082,17890724,TMAX,231,,,E, +EZE00100082,17890724,TMIN,158,,,E, +ITE00100554,17890724,TMAX,263,,,E, +ITE00100554,17890724,TMIN,188,,,E, +GM000010962,17890724,PRCP,4,,,E, +EZE00100082,17890725,TMAX,237,,,E, +EZE00100082,17890725,TMIN,149,,,E, +ITE00100554,17890725,TMAX,263,,,E, +ITE00100554,17890725,TMIN,204,,,E, +GM000010962,17890725,PRCP,0,,,E, +EZE00100082,17890726,TMAX,251,,,E, +EZE00100082,17890726,TMIN,176,,,E, +ITE00100554,17890726,TMAX,275,,,E, +ITE00100554,17890726,TMIN,191,,,E, +GM000010962,17890726,PRCP,0,,,E, +EZE00100082,17890727,TMAX,250,,,E, +EZE00100082,17890727,TMIN,170,,,E, +ITE00100554,17890727,TMAX,288,,,E, +ITE00100554,17890727,TMIN,225,,I,E, +GM000010962,17890727,PRCP,0,,,E, +EZE00100082,17890728,TMAX,240,,,E, +EZE00100082,17890728,TMIN,185,,,E, +ITE00100554,17890728,TMAX,206,,I,E, +ITE00100554,17890728,TMIN,200,,,E, +GM000010962,17890728,PRCP,112,,,E, +EZE00100082,17890729,TMAX,250,,,E, +EZE00100082,17890729,TMIN,169,,,E, +ITE00100554,17890729,TMAX,235,,,E, +ITE00100554,17890729,TMIN,181,,,E, +GM000010962,17890729,PRCP,209,,,E, +EZE00100082,17890730,TMAX,204,,,E, +EZE00100082,17890730,TMIN,163,,,E, +ITE00100554,17890730,TMAX,281,,,E, +ITE00100554,17890730,TMIN,200,,,E, +GM000010962,17890730,PRCP,147,,,E, +EZE00100082,17890731,TMAX,230,,,E, +EZE00100082,17890731,TMIN,177,,,E, +ITE00100554,17890731,TMAX,281,,,E, +ITE00100554,17890731,TMIN,195,,,E, +GM000010962,17890731,PRCP,0,,,E, +EZE00100082,17890801,TMAX,214,,,E, +EZE00100082,17890801,TMIN,163,,,E, +ITE00100554,17890801,TMAX,281,,,E, +ITE00100554,17890801,TMIN,200,,,E, +GM000010962,17890801,PRCP,56,,,E, +EZE00100082,17890802,TMAX,175,,,E, +EZE00100082,17890802,TMIN,163,,,E, +ITE00100554,17890802,TMAX,269,,,E, +ITE00100554,17890802,TMIN,203,,,E, +GM000010962,17890802,PRCP,0,,,E, +EZE00100082,17890803,TMAX,233,,,E, +EZE00100082,17890803,TMIN,168,,,E, +ITE00100554,17890803,TMAX,265,,,E, +ITE00100554,17890803,TMIN,184,,,E, +GM000010962,17890803,PRCP,4,,,E, +EZE00100082,17890804,TMAX,242,,,E, +EZE00100082,17890804,TMIN,169,,,E, +ITE00100554,17890804,TMAX,281,,,E, +ITE00100554,17890804,TMIN,204,,,E, +GM000010962,17890804,PRCP,0,,,E, +EZE00100082,17890805,TMAX,270,,,E, +EZE00100082,17890805,TMIN,177,,,E, +ITE00100554,17890805,TMAX,281,,,E, +ITE00100554,17890805,TMIN,204,,,E, +GM000010962,17890805,PRCP,0,,,E, +EZE00100082,17890806,TMAX,273,,,E, +EZE00100082,17890806,TMIN,150,,,E, +ITE00100554,17890806,TMAX,315,,,E, +ITE00100554,17890806,TMIN,225,,,E, +GM000010962,17890806,PRCP,0,,,E, +EZE00100082,17890807,TMAX,228,,,E, +EZE00100082,17890807,TMIN,155,,,E, +ITE00100554,17890807,TMAX,310,,,E, +ITE00100554,17890807,TMIN,238,,,E, +GM000010962,17890807,PRCP,2,,,E, +EZE00100082,17890808,TMAX,224,,,E, +EZE00100082,17890808,TMIN,166,,,E, +ITE00100554,17890808,TMAX,313,,,E, +ITE00100554,17890808,TMIN,245,,,E, +GM000010962,17890808,PRCP,0,,,E, +EZE00100082,17890809,TMAX,227,,,E, +EZE00100082,17890809,TMIN,158,,,E, +ITE00100554,17890809,TMAX,328,,,E, +ITE00100554,17890809,TMIN,246,,,E, +GM000010962,17890809,PRCP,0,,,E, +EZE00100082,17890810,TMAX,251,,,E, +EZE00100082,17890810,TMIN,158,,,E, +ITE00100554,17890810,TMAX,294,,,E, +ITE00100554,17890810,TMIN,223,,,E, +GM000010962,17890810,PRCP,0,,,E, +EZE00100082,17890811,TMAX,260,,,E, +EZE00100082,17890811,TMIN,169,,,E, +ITE00100554,17890811,TMAX,288,,,E, +ITE00100554,17890811,TMIN,231,,,E, +GM000010962,17890811,PRCP,0,,,E, +EZE00100082,17890812,TMAX,240,,,E, +EZE00100082,17890812,TMIN,160,,,E, +ITE00100554,17890812,TMAX,278,,,E, +ITE00100554,17890812,TMIN,208,,,E, +GM000010962,17890812,PRCP,0,,,E, +EZE00100082,17890813,TMAX,250,,,E, +EZE00100082,17890813,TMIN,161,,,E, +ITE00100554,17890813,TMAX,278,,,E, +ITE00100554,17890813,TMIN,203,,,E, +GM000010962,17890813,PRCP,0,,,E, +EZE00100082,17890814,TMAX,222,,,E, +EZE00100082,17890814,TMIN,125,,,E, +ITE00100554,17890814,TMAX,265,,,E, +ITE00100554,17890814,TMIN,206,,,E, +GM000010962,17890814,PRCP,12,,,E, +EZE00100082,17890815,TMAX,236,,,E, +EZE00100082,17890815,TMIN,155,,,E, +ITE00100554,17890815,TMAX,231,,,E, +ITE00100554,17890815,TMIN,206,,,E, +GM000010962,17890815,PRCP,2,,,E, +EZE00100082,17890816,TMAX,246,,,E, +EZE00100082,17890816,TMIN,156,,,E, +ITE00100554,17890816,TMAX,248,,,E, +ITE00100554,17890816,TMIN,194,,,E, +GM000010962,17890816,PRCP,3,,,E, +EZE00100082,17890817,TMAX,250,,,E, +EZE00100082,17890817,TMIN,156,,,E, +ITE00100554,17890817,TMAX,216,,,E, +ITE00100554,17890817,TMIN,181,,,E, +GM000010962,17890817,PRCP,93,,,E, +EZE00100082,17890818,TMAX,237,,,E, +EZE00100082,17890818,TMIN,163,,,E, +ITE00100554,17890818,TMAX,246,,,E, +ITE00100554,17890818,TMIN,181,,,E, +GM000010962,17890818,PRCP,0,,,E, +EZE00100082,17890819,TMAX,235,,,E, +EZE00100082,17890819,TMIN,158,,,E, +ITE00100554,17890819,TMAX,256,,,E, +ITE00100554,17890819,TMIN,188,,,E, +GM000010962,17890819,PRCP,0,,,E, +EZE00100082,17890820,TMAX,255,,,E, +EZE00100082,17890820,TMIN,156,,,E, +ITE00100554,17890820,TMAX,265,,,E, +ITE00100554,17890820,TMIN,188,,,E, +GM000010962,17890820,PRCP,0,,,E, +EZE00100082,17890821,TMAX,263,,,E, +EZE00100082,17890821,TMIN,147,,,E, +ITE00100554,17890821,TMAX,253,,,E, +ITE00100554,17890821,TMIN,200,,,E, +GM000010962,17890821,PRCP,0,,,E, +EZE00100082,17890822,TMAX,260,,,E, +EZE00100082,17890822,TMIN,164,,,E, +ITE00100554,17890822,TMAX,225,,,E, +ITE00100554,17890822,TMIN,200,,,E, +GM000010962,17890822,PRCP,157,,,E, +EZE00100082,17890823,TMAX,198,,,E, +EZE00100082,17890823,TMIN,153,,,E, +ITE00100554,17890823,TMAX,219,,,E, +ITE00100554,17890823,TMIN,175,,,E, +GM000010962,17890823,PRCP,263,,,E, +EZE00100082,17890824,TMAX,186,,,E, +EZE00100082,17890824,TMIN,148,,,E, +ITE00100554,17890824,TMAX,216,,,E, +ITE00100554,17890824,TMIN,169,,,E, +GM000010962,17890824,PRCP,0,,,E, +EZE00100082,17890825,TMAX,173,,,E, +EZE00100082,17890825,TMIN,144,,,E, +ITE00100554,17890825,TMAX,245,,,E, +ITE00100554,17890825,TMIN,158,,,E, +GM000010962,17890825,PRCP,4,,,E, +EZE00100082,17890826,TMAX,193,,,E, +EZE00100082,17890826,TMIN,155,,,E, +ITE00100554,17890826,TMAX,250,,,E, +ITE00100554,17890826,TMIN,166,,,E, +GM000010962,17890826,PRCP,0,,,E, +EZE00100082,17890827,TMAX,223,,,E, +EZE00100082,17890827,TMIN,152,,,E, +ITE00100554,17890827,TMAX,258,,,E, +ITE00100554,17890827,TMIN,188,,,E, +GM000010962,17890827,PRCP,0,,,E, +EZE00100082,17890828,TMAX,230,,,E, +EZE00100082,17890828,TMIN,153,,,E, +ITE00100554,17890828,TMAX,266,,,E, +ITE00100554,17890828,TMIN,191,,,E, +GM000010962,17890828,PRCP,0,,,E, +EZE00100082,17890829,TMAX,235,,,E, +EZE00100082,17890829,TMIN,142,,,E, +ITE00100554,17890829,TMAX,269,,,E, +ITE00100554,17890829,TMIN,200,,,E, +GM000010962,17890829,PRCP,0,,,E, +EZE00100082,17890830,TMAX,221,,,E, +EZE00100082,17890830,TMIN,119,,,E, +ITE00100554,17890830,TMAX,269,,,E, +ITE00100554,17890830,TMIN,208,,,E, +GM000010962,17890830,PRCP,0,,,E, +EZE00100082,17890831,TMAX,230,,,E, +EZE00100082,17890831,TMIN,145,,,E, +ITE00100554,17890831,TMAX,213,,,E, +ITE00100554,17890831,TMIN,200,,,E, +GM000010962,17890831,PRCP,2,,,E, +EZE00100082,17890901,TMAX,200,,,E, +EZE00100082,17890901,TMIN,145,,,E, +ITE00100554,17890901,TMAX,225,,,E, +ITE00100554,17890901,TMIN,179,,,E, +GM000010962,17890901,PRCP,179,,,E, +EZE00100082,17890902,TMAX,222,,,E, +EZE00100082,17890902,TMIN,138,,,E, +ITE00100554,17890902,TMAX,231,,,E, +ITE00100554,17890902,TMIN,181,,,E, +GM000010962,17890902,PRCP,0,,,E, +EZE00100082,17890903,TMAX,225,,,E, +EZE00100082,17890903,TMIN,169,,,E, +ITE00100554,17890903,TMAX,256,,,E, +ITE00100554,17890903,TMIN,190,,,E, +GM000010962,17890903,PRCP,0,,,E, +EZE00100082,17890904,TMAX,237,,,E, +EZE00100082,17890904,TMIN,162,,,E, +ITE00100554,17890904,TMAX,250,,,E, +ITE00100554,17890904,TMIN,158,,,E, +GM000010962,17890904,PRCP,0,,,E, +EZE00100082,17890905,TMAX,223,,,E, +EZE00100082,17890905,TMIN,169,,,E, +ITE00100554,17890905,TMAX,265,,,E, +ITE00100554,17890905,TMIN,213,,,E, +GM000010962,17890905,PRCP,44,,,E, +EZE00100082,17890906,TMAX,240,,,E, +EZE00100082,17890906,TMIN,162,,,E, +ITE00100554,17890906,TMAX,265,,,E, +ITE00100554,17890906,TMIN,191,,,E, +GM000010962,17890906,PRCP,0,,,E, +EZE00100082,17890907,TMAX,195,,,E, +EZE00100082,17890907,TMIN,151,,,E, +ITE00100554,17890907,TMAX,275,,,E, +ITE00100554,17890907,TMIN,200,,,E, +GM000010962,17890907,PRCP,26,,,E, +EZE00100082,17890908,TMAX,214,,,E, +EZE00100082,17890908,TMIN,152,,,E, +ITE00100554,17890908,TMAX,238,,,E, +ITE00100554,17890908,TMIN,200,,,E, +GM000010962,17890908,PRCP,73,,,E, +EZE00100082,17890909,TMAX,222,,,E, +EZE00100082,17890909,TMIN,151,,,E, +ITE00100554,17890909,TMAX,254,,,E, +ITE00100554,17890909,TMIN,188,,,E, +GM000010962,17890909,PRCP,0,,,E, +EZE00100082,17890910,TMAX,242,,,E, +EZE00100082,17890910,TMIN,154,,,E, +ITE00100554,17890910,TMAX,254,,,E, +ITE00100554,17890910,TMIN,179,,,E, +GM000010962,17890910,PRCP,0,,,E, +EZE00100082,17890911,TMAX,255,,,E, +EZE00100082,17890911,TMIN,140,,,E, +ITE00100554,17890911,TMAX,250,,,E, +ITE00100554,17890911,TMIN,190,,,E, +GM000010962,17890911,PRCP,0,,,E, +EZE00100082,17890912,TMAX,200,,,E, +EZE00100082,17890912,TMIN,140,,,E, +ITE00100554,17890912,TMAX,263,,,E, +ITE00100554,17890912,TMIN,200,,,E, +GM000010962,17890912,PRCP,35,,,E, +EZE00100082,17890913,TMAX,191,,,E, +EZE00100082,17890913,TMIN,132,,,E, +ITE00100554,17890913,TMAX,220,,,E, +ITE00100554,17890913,TMIN,181,,,E, +GM000010962,17890913,PRCP,72,,,E, +EZE00100082,17890914,TMAX,210,,,E, +EZE00100082,17890914,TMIN,111,,,E, +ITE00100554,17890914,TMAX,203,,,E, +ITE00100554,17890914,TMIN,179,,,E, +GM000010962,17890914,PRCP,13,,,E, +EZE00100082,17890915,TMAX,214,,,E, +EZE00100082,17890915,TMIN,146,,,E, +ITE00100554,17890915,TMAX,238,,,E, +ITE00100554,17890915,TMIN,181,,,E, +GM000010962,17890915,PRCP,18,,,E, +EZE00100082,17890916,TMAX,194,,,E, +EZE00100082,17890916,TMIN,143,,,E, +ITE00100554,17890916,TMAX,203,,,E, +ITE00100554,17890916,TMIN,181,,I,E, +GM000010962,17890916,PRCP,29,,,E, +EZE00100082,17890917,TMAX,181,,,E, +EZE00100082,17890917,TMIN,139,,,E, +ITE00100554,17890917,TMAX,160,,I,E, +ITE00100554,17890917,TMIN,153,,,E, +GM000010962,17890917,PRCP,153,,,E, +EZE00100082,17890918,TMAX,165,,,E, +EZE00100082,17890918,TMIN,98,,,E, +ITE00100554,17890918,TMAX,179,,,E, +ITE00100554,17890918,TMIN,125,,,E, +GM000010962,17890918,PRCP,48,,,E, +EZE00100082,17890919,TMAX,152,,,E, +EZE00100082,17890919,TMIN,96,,,E, +ITE00100554,17890919,TMAX,175,,,E, +ITE00100554,17890919,TMIN,113,,,E, +GM000010962,17890919,PRCP,0,,,E, +EZE00100082,17890920,TMAX,142,,,E, +EZE00100082,17890920,TMIN,110,,,E, +ITE00100554,17890920,TMAX,175,,,E, +ITE00100554,17890920,TMIN,140,,,E, +GM000010962,17890920,PRCP,47,,,E, +EZE00100082,17890921,TMAX,150,,,E, +EZE00100082,17890921,TMIN,117,,,E, +ITE00100554,17890921,TMAX,200,,,E, +ITE00100554,17890921,TMIN,119,,,E, +GM000010962,17890921,PRCP,6,,,E, +EZE00100082,17890922,TMAX,143,,,E, +EZE00100082,17890922,TMIN,121,,,E, +ITE00100554,17890922,TMAX,210,,,E, +ITE00100554,17890922,TMIN,156,,,E, +GM000010962,17890922,PRCP,12,,,E, +EZE00100082,17890923,TMAX,161,,,E, +EZE00100082,17890923,TMIN,113,,,E, +ITE00100554,17890923,TMAX,213,,,E, +ITE00100554,17890923,TMIN,150,,,E, +GM000010962,17890923,PRCP,0,,,E, +EZE00100082,17890924,TMAX,125,,,E, +EZE00100082,17890924,TMIN,100,,,E, +ITE00100554,17890924,TMAX,213,,,E, +ITE00100554,17890924,TMIN,150,,,E, +GM000010962,17890924,PRCP,79,,,E, +EZE00100082,17890925,TMAX,141,,,E, +EZE00100082,17890925,TMIN,100,,,E, +ITE00100554,17890925,TMAX,213,,,E, +ITE00100554,17890925,TMIN,131,,,E, +GM000010962,17890925,PRCP,79,,,E, +EZE00100082,17890926,TMAX,157,,,E, +EZE00100082,17890926,TMIN,98,,,E, +ITE00100554,17890926,TMAX,200,,,E, +ITE00100554,17890926,TMIN,131,,,E, +GM000010962,17890926,PRCP,0,,,E, +EZE00100082,17890927,TMAX,183,,,E, +EZE00100082,17890927,TMIN,92,,,E, +ITE00100554,17890927,TMAX,213,,,E, +ITE00100554,17890927,TMIN,138,,,E, +GM000010962,17890927,PRCP,0,,,E, +EZE00100082,17890928,TMAX,195,,,E, +EZE00100082,17890928,TMIN,120,,,E, +ITE00100554,17890928,TMAX,215,,,E, +ITE00100554,17890928,TMIN,153,,,E, +GM000010962,17890928,PRCP,0,,,E, +EZE00100082,17890929,TMAX,185,,,E, +EZE00100082,17890929,TMIN,104,,,E, +ITE00100554,17890929,TMAX,216,,,E, +ITE00100554,17890929,TMIN,153,,,E, +GM000010962,17890929,PRCP,0,,,E, +EZE00100082,17890930,TMAX,216,,,E, +EZE00100082,17890930,TMIN,97,,,E, +ITE00100554,17890930,TMAX,220,,,E, +ITE00100554,17890930,TMIN,156,,,E, +GM000010962,17890930,PRCP,0,,,E, +EZE00100082,17891001,TMAX,210,,,E, +EZE00100082,17891001,TMIN,130,,,E, +ITE00100554,17891001,TMAX,219,,,E, +ITE00100554,17891001,TMIN,156,,,E, +GM000010962,17891001,PRCP,0,,,E, +EZE00100082,17891002,TMAX,155,,,E, +EZE00100082,17891002,TMIN,106,,,E, +ITE00100554,17891002,TMAX,169,,,E, +ITE00100554,17891002,TMIN,158,,,E, +GM000010962,17891002,PRCP,13,,,E, +EZE00100082,17891003,TMAX,145,,,E, +EZE00100082,17891003,TMIN,88,,,E, +ITE00100554,17891003,TMAX,181,,,E, +ITE00100554,17891003,TMIN,158,,,E, +GM000010962,17891003,PRCP,76,,,E, +EZE00100082,17891004,TMAX,155,,,E, +EZE00100082,17891004,TMIN,99,,,E, +ITE00100554,17891004,TMAX,181,,,E, +ITE00100554,17891004,TMIN,113,,,E, +GM000010962,17891004,PRCP,31,,,E, +EZE00100082,17891005,TMAX,107,,,E, +EZE00100082,17891005,TMIN,96,,,E, +ITE00100554,17891005,TMAX,156,,,E, +ITE00100554,17891005,TMIN,119,,,E, +GM000010962,17891005,PRCP,204,,,E, +EZE00100082,17891006,TMAX,150,,,E, +EZE00100082,17891006,TMIN,80,,,E, +ITE00100554,17891006,TMAX,154,,,E, +ITE00100554,17891006,TMIN,119,,,E, +GM000010962,17891006,PRCP,5,,,E, +EZE00100082,17891007,TMAX,144,,,E, +EZE00100082,17891007,TMIN,65,,,E, +ITE00100554,17891007,TMAX,148,,,E, +ITE00100554,17891007,TMIN,94,,,E, +GM000010962,17891007,PRCP,1,,,E, +EZE00100082,17891008,TMAX,144,,,E, +EZE00100082,17891008,TMIN,58,,,E, +ITE00100554,17891008,TMAX,141,,,E, +ITE00100554,17891008,TMIN,125,,,E, +GM000010962,17891008,PRCP,0,,,E, +EZE00100082,17891009,TMAX,182,,,E, +EZE00100082,17891009,TMIN,87,,,E, +ITE00100554,17891009,TMAX,188,,,E, +ITE00100554,17891009,TMIN,133,,,E, +GM000010962,17891009,PRCP,0,,,E, +EZE00100082,17891010,TMAX,173,,,E, +EZE00100082,17891010,TMIN,136,,,E, +ITE00100554,17891010,TMAX,158,,,E, +ITE00100554,17891010,TMIN,150,,,E, +GM000010962,17891010,PRCP,89,,,E, +EZE00100082,17891011,TMAX,155,,,E, +EZE00100082,17891011,TMIN,116,,,E, +ITE00100554,17891011,TMAX,169,,,E, +ITE00100554,17891011,TMIN,104,,,E, +GM000010962,17891011,PRCP,16,,,E, +EZE00100082,17891012,TMAX,183,,,E, +EZE00100082,17891012,TMIN,111,,,E, +ITE00100554,17891012,TMAX,169,,,E, +ITE00100554,17891012,TMIN,94,,,E, +GM000010962,17891012,PRCP,0,,,E, +EZE00100082,17891013,TMAX,150,,,E, +EZE00100082,17891013,TMIN,90,,,E, +ITE00100554,17891013,TMAX,175,,,E, +ITE00100554,17891013,TMIN,131,,,E, +GM000010962,17891013,PRCP,0,,,E, +EZE00100082,17891014,TMAX,152,,,E, +EZE00100082,17891014,TMIN,100,,,E, +ITE00100554,17891014,TMAX,150,,,E, +ITE00100554,17891014,TMIN,125,,,E, +GM000010962,17891014,PRCP,0,,,E, +EZE00100082,17891015,TMAX,175,,,E, +EZE00100082,17891015,TMIN,105,,,E, +ITE00100554,17891015,TMAX,150,,,E, +ITE00100554,17891015,TMIN,131,,,E, +GM000010962,17891015,PRCP,0,,,E, +EZE00100082,17891016,TMAX,140,,,E, +EZE00100082,17891016,TMIN,106,,,E, +ITE00100554,17891016,TMAX,156,,,E, +ITE00100554,17891016,TMIN,113,,,E, +GM000010962,17891016,PRCP,51,,,E, +EZE00100082,17891017,TMAX,151,,,E, +EZE00100082,17891017,TMIN,105,,,E, +ITE00100554,17891017,TMAX,194,,,E, +ITE00100554,17891017,TMIN,125,,,E, +GM000010962,17891017,PRCP,26,,,E, +EZE00100082,17891018,TMAX,138,,,E, +EZE00100082,17891018,TMIN,110,,,E, +ITE00100554,17891018,TMAX,169,,,E, +ITE00100554,17891018,TMIN,106,,,E, +GM000010962,17891018,PRCP,3,,,E, +EZE00100082,17891019,TMAX,142,,,E, +EZE00100082,17891019,TMIN,107,,,E, +ITE00100554,17891019,TMAX,156,,,E, +ITE00100554,17891019,TMIN,106,,,E, +GM000010962,17891019,PRCP,0,,,E, +EZE00100082,17891020,TMAX,150,,,E, +EZE00100082,17891020,TMIN,94,,,E, +ITE00100554,17891020,TMAX,169,,,E, +ITE00100554,17891020,TMIN,106,,,E, +GM000010962,17891020,PRCP,33,,,E, +EZE00100082,17891021,TMAX,120,,,E, +EZE00100082,17891021,TMIN,74,,,E, +ITE00100554,17891021,TMAX,154,,,E, +ITE00100554,17891021,TMIN,106,,,E, +GM000010962,17891021,PRCP,0,,,E, +EZE00100082,17891022,TMAX,89,,,E, +EZE00100082,17891022,TMIN,60,,,E, +ITE00100554,17891022,TMAX,150,,,E, +ITE00100554,17891022,TMIN,98,,,E, +GM000010962,17891022,PRCP,0,,,E, +EZE00100082,17891023,TMAX,113,,,E, +EZE00100082,17891023,TMIN,59,,,E, +ITE00100554,17891023,TMAX,150,,,E, +ITE00100554,17891023,TMIN,128,,,E, +GM000010962,17891023,PRCP,3,,,E, +EZE00100082,17891024,TMAX,95,,,E, +EZE00100082,17891024,TMIN,59,,,E, +ITE00100554,17891024,TMAX,125,,,E, +ITE00100554,17891024,TMIN,123,,,E, +GM000010962,17891024,PRCP,0,,,E, +EZE00100082,17891025,TMAX,101,,,E, +EZE00100082,17891025,TMIN,22,,,E, +ITE00100554,17891025,TMAX,144,,,E, +ITE00100554,17891025,TMIN,119,,,E, +GM000010962,17891025,PRCP,0,,,E, +EZE00100082,17891026,TMAX,109,,,E, +EZE00100082,17891026,TMIN,17,,,E, +ITE00100554,17891026,TMAX,119,,,E, +ITE00100554,17891026,TMIN,119,,,E, +GM000010962,17891026,PRCP,0,,,E, +EZE00100082,17891027,TMAX,113,,,E, +EZE00100082,17891027,TMIN,16,,,E, +ITE00100554,17891027,TMAX,119,,,E, +ITE00100554,17891027,TMIN,103,,,E, +GM000010962,17891027,PRCP,0,,,E, +EZE00100082,17891028,TMAX,91,,,E, +EZE00100082,17891028,TMIN,30,,,E, +ITE00100554,17891028,TMAX,116,,,E, +ITE00100554,17891028,TMIN,104,,,E, +GM000010962,17891028,PRCP,11,,,E, +EZE00100082,17891029,TMAX,83,,,E, +EZE00100082,17891029,TMIN,32,,,E, +ITE00100554,17891029,TMAX,128,,,E, +ITE00100554,17891029,TMIN,113,,,E, +GM000010962,17891029,PRCP,15,,,E, +EZE00100082,17891030,TMAX,100,,,E, +EZE00100082,17891030,TMIN,68,,,E, +ITE00100554,17891030,TMAX,128,,,E, +ITE00100554,17891030,TMIN,100,,,E, +GM000010962,17891030,PRCP,38,,,E, +EZE00100082,17891031,TMAX,112,,,E, +EZE00100082,17891031,TMIN,67,,,E, +ITE00100554,17891031,TMAX,125,,,E, +ITE00100554,17891031,TMIN,113,,,E, +GM000010962,17891031,PRCP,2,,,E, +EZE00100082,17891101,TMAX,90,,,E, +EZE00100082,17891101,TMIN,58,,,E, +ITE00100554,17891101,TMAX,125,,,E, +ITE00100554,17891101,TMIN,109,,,E, +GM000010962,17891101,PRCP,22,,,E, +EZE00100082,17891102,TMAX,138,,,E, +EZE00100082,17891102,TMIN,58,,,E, +ITE00100554,17891102,TMAX,115,,,E, +ITE00100554,17891102,TMIN,96,,,E, +GM000010962,17891102,PRCP,8,,,E, +EZE00100082,17891103,TMAX,131,,,E, +EZE00100082,17891103,TMIN,85,,,E, +ITE00100554,17891103,TMAX,106,,,E, +ITE00100554,17891103,TMIN,94,,,E, +GM000010962,17891103,PRCP,3,,,E, +EZE00100082,17891104,TMAX,116,,,E, +EZE00100082,17891104,TMIN,54,,,E, +ITE00100554,17891104,TMAX,128,,,E, +ITE00100554,17891104,TMIN,94,,,E, +GM000010962,17891104,PRCP,0,,,E, +EZE00100082,17891105,TMAX,88,,,E, +EZE00100082,17891105,TMIN,25,,,E, +ITE00100554,17891105,TMAX,106,,,E, +ITE00100554,17891105,TMIN,106,,,E, +GM000010962,17891105,PRCP,0,,,E, +EZE00100082,17891106,TMAX,116,,,E, +EZE00100082,17891106,TMIN,52,,,E, +ITE00100554,17891106,TMAX,103,,,E, +ITE00100554,17891106,TMIN,90,,,E, +GM000010962,17891106,PRCP,0,,,E, +EZE00100082,17891107,TMAX,96,,,E, +EZE00100082,17891107,TMIN,43,,,E, +ITE00100554,17891107,TMAX,115,,,E, +ITE00100554,17891107,TMIN,91,,,E, +GM000010962,17891107,PRCP,0,,,E, +EZE00100082,17891108,TMAX,85,,,E, +EZE00100082,17891108,TMIN,38,,,E, +ITE00100554,17891108,TMAX,94,,,E, +ITE00100554,17891108,TMIN,75,,,E, +GM000010962,17891108,PRCP,16,,,E, +EZE00100082,17891109,TMAX,80,,,E, +EZE00100082,17891109,TMIN,38,,,E, +ITE00100554,17891109,TMAX,81,,,E, +ITE00100554,17891109,TMIN,46,,,E, +GM000010962,17891109,PRCP,4,,,E, +EZE00100082,17891110,TMAX,71,,,E, +EZE00100082,17891110,TMIN,30,,,E, +ITE00100554,17891110,TMAX,81,,,E, +ITE00100554,17891110,TMIN,34,,,E, +GM000010962,17891110,PRCP,0,,,E, +EZE00100082,17891111,TMAX,77,,,E, +EZE00100082,17891111,TMIN,32,,,E, +ITE00100554,17891111,TMAX,69,,,E, +ITE00100554,17891111,TMIN,38,,,E, +GM000010962,17891111,PRCP,0,,,E, +EZE00100082,17891112,TMAX,72,,,E, +EZE00100082,17891112,TMIN,50,,,E, +ITE00100554,17891112,TMAX,70,,,E, +ITE00100554,17891112,TMIN,31,,,E, +GM000010962,17891112,PRCP,0,,,E, +EZE00100082,17891113,TMAX,87,,,E, +EZE00100082,17891113,TMIN,40,,,E, +ITE00100554,17891113,TMAX,78,,,E, +ITE00100554,17891113,TMIN,46,,,E, +GM000010962,17891113,PRCP,6,,,E, +EZE00100082,17891114,TMAX,112,,,E, +EZE00100082,17891114,TMIN,63,,,E, +ITE00100554,17891114,TMAX,75,,,E, +ITE00100554,17891114,TMIN,25,,,E, +GM000010962,17891114,PRCP,7,,,E, +EZE00100082,17891115,TMAX,126,,,E, +EZE00100082,17891115,TMIN,92,,,E, +ITE00100554,17891115,TMAX,75,,,E, +ITE00100554,17891115,TMIN,50,,,E, +GM000010962,17891115,PRCP,4,,,E, +EZE00100082,17891116,TMAX,127,,,E, +EZE00100082,17891116,TMIN,87,,,E, +ITE00100554,17891116,TMAX,75,,,E, +ITE00100554,17891116,TMIN,56,,,E, +GM000010962,17891116,PRCP,0,,,E, +EZE00100082,17891117,TMAX,90,,,E, +EZE00100082,17891117,TMIN,43,,,E, +ITE00100554,17891117,TMAX,75,,,E, +ITE00100554,17891117,TMIN,69,,,E, +GM000010962,17891117,PRCP,0,,,E, +EZE00100082,17891118,TMAX,83,,,E, +EZE00100082,17891118,TMIN,44,,,E, +ITE00100554,17891118,TMAX,94,,,E, +ITE00100554,17891118,TMIN,63,,,E, +GM000010962,17891118,PRCP,17,,,E, +EZE00100082,17891119,TMAX,95,,,E, +EZE00100082,17891119,TMIN,66,,,E, +ITE00100554,17891119,TMAX,56,,,E, +ITE00100554,17891119,TMIN,38,,,E, +GM000010962,17891119,PRCP,6,,,E, +EZE00100082,17891120,TMAX,102,,,E, +EZE00100082,17891120,TMIN,68,,,E, +ITE00100554,17891120,TMAX,63,,,E, +ITE00100554,17891120,TMIN,50,,,E, +GM000010962,17891120,PRCP,0,,,E, +EZE00100082,17891121,TMAX,82,,,E, +EZE00100082,17891121,TMIN,57,,,E, +ITE00100554,17891121,TMAX,56,,,E, +ITE00100554,17891121,TMIN,13,,,E, +GM000010962,17891121,PRCP,3,,,E, +EZE00100082,17891122,TMAX,60,,,E, +EZE00100082,17891122,TMIN,48,,,E, +ITE00100554,17891122,TMAX,53,,,E, +ITE00100554,17891122,TMIN,19,,,E, +GM000010962,17891122,PRCP,0,,,E, +EZE00100082,17891123,TMAX,57,,,E, +EZE00100082,17891123,TMIN,10,,,E, +ITE00100554,17891123,TMAX,50,,,E, +ITE00100554,17891123,TMIN,13,,,E, +GM000010962,17891123,PRCP,0,,,E, +EZE00100082,17891124,TMAX,10,,,E, +EZE00100082,17891124,TMIN,-13,,,E, +ITE00100554,17891124,TMAX,50,,,E, +ITE00100554,17891124,TMIN,13,,,E, +GM000010962,17891124,PRCP,16,,,E, +EZE00100082,17891125,TMAX,5,,,E, +EZE00100082,17891125,TMIN,-20,,,E, +ITE00100554,17891125,TMAX,13,,,E, +ITE00100554,17891125,TMIN,0,,,E, +GM000010962,17891125,PRCP,6,,,E, +EZE00100082,17891126,TMAX,-11,,,E, +EZE00100082,17891126,TMIN,-52,,,E, +ITE00100554,17891126,TMAX,0,,,E, +ITE00100554,17891126,TMIN,-25,,,E, +GM000010962,17891126,PRCP,0,,,E, +EZE00100082,17891127,TMAX,21,,,E, +EZE00100082,17891127,TMIN,-11,,,E, +ITE00100554,17891127,TMAX,13,,,E, +ITE00100554,17891127,TMIN,-34,,,E, +GM000010962,17891127,PRCP,0,,,E, +EZE00100082,17891128,TMAX,45,,,E, +EZE00100082,17891128,TMIN,21,,,E, +ITE00100554,17891128,TMAX,21,,,E, +ITE00100554,17891128,TMIN,-28,,,E, +GM000010962,17891128,PRCP,14,,,E, +EZE00100082,17891129,TMAX,51,,,E, +EZE00100082,17891129,TMIN,28,,,E, +ITE00100554,17891129,TMAX,0,,,E, +ITE00100554,17891129,TMIN,-25,,,E, +GM000010962,17891129,PRCP,7,,,E, +EZE00100082,17891130,TMAX,51,,,E, +EZE00100082,17891130,TMIN,10,,,E, +ITE00100554,17891130,TMAX,21,,,E, +ITE00100554,17891130,TMIN,-25,,,E, +GM000010962,17891130,PRCP,0,,,E, +EZE00100082,17891201,TMAX,24,,,E, +EZE00100082,17891201,TMIN,-11,,,E, +ITE00100554,17891201,TMAX,25,,,E, +ITE00100554,17891201,TMIN,-25,,,E, +GM000010962,17891201,PRCP,0,,,E, +EZE00100082,17891202,TMAX,15,,,E, +EZE00100082,17891202,TMIN,-19,,,E, +ITE00100554,17891202,TMAX,20,,,E, +ITE00100554,17891202,TMIN,-21,,,E, +GM000010962,17891202,PRCP,0,,,E, +EZE00100082,17891203,TMAX,13,,,E, +EZE00100082,17891203,TMIN,-6,,,E, +ITE00100554,17891203,TMAX,16,,,E, +ITE00100554,17891203,TMIN,8,,,E, +GM000010962,17891203,PRCP,0,,,E, +EZE00100082,17891204,TMAX,-6,,,E, +EZE00100082,17891204,TMIN,-8,,,E, +ITE00100554,17891204,TMAX,19,,,E, +ITE00100554,17891204,TMIN,13,,,E, +GM000010962,17891204,PRCP,0,,,E, +EZE00100082,17891205,TMAX,-4,,,E, +EZE00100082,17891205,TMIN,-7,,,E, +ITE00100554,17891205,TMAX,19,,,E, +ITE00100554,17891205,TMIN,0,,,E, +GM000010962,17891205,PRCP,0,,,E, +EZE00100082,17891206,TMAX,29,,,E, +EZE00100082,17891206,TMIN,-7,,,E, +ITE00100554,17891206,TMAX,40,,,E, +ITE00100554,17891206,TMIN,-8,,,E, +GM000010962,17891206,PRCP,4,,,E, +EZE00100082,17891207,TMAX,53,,,E, +EZE00100082,17891207,TMIN,29,,,E, +ITE00100554,17891207,TMAX,45,,,E, +ITE00100554,17891207,TMIN,0,,,E, +GM000010962,17891207,PRCP,0,,,E, +EZE00100082,17891208,TMAX,41,,,E, +EZE00100082,17891208,TMIN,26,,,E, +ITE00100554,17891208,TMAX,45,,,E, +ITE00100554,17891208,TMIN,6,,,E, +GM000010962,17891208,PRCP,4,,,E, +EZE00100082,17891209,TMAX,26,,,E, +EZE00100082,17891209,TMIN,8,,,E, +ITE00100554,17891209,TMAX,0,,,E, +ITE00100554,17891209,TMIN,-13,,,E, +GM000010962,17891209,PRCP,3,,,E, +EZE00100082,17891210,TMAX,23,,,E, +EZE00100082,17891210,TMIN,-11,,,E, +ITE00100554,17891210,TMAX,0,,,E, +ITE00100554,17891210,TMIN,-31,,,E, +GM000010962,17891210,PRCP,0,,,E, +EZE00100082,17891211,TMAX,40,,,E, +EZE00100082,17891211,TMIN,10,,,E, +ITE00100554,17891211,TMAX,0,,,E, +ITE00100554,17891211,TMIN,-41,,,E, +GM000010962,17891211,PRCP,0,,,E, +EZE00100082,17891212,TMAX,42,,,E, +EZE00100082,17891212,TMIN,11,,,E, +ITE00100554,17891212,TMAX,0,,,E, +ITE00100554,17891212,TMIN,-34,,,E, +GM000010962,17891212,PRCP,0,,,E, +EZE00100082,17891213,TMAX,45,,,E, +EZE00100082,17891213,TMIN,29,,,E, +ITE00100554,17891213,TMAX,13,,,E, +ITE00100554,17891213,TMIN,-28,,,E, +GM000010962,17891213,PRCP,0,,,E, +EZE00100082,17891214,TMAX,31,,,E, +EZE00100082,17891214,TMIN,15,,,E, +ITE00100554,17891214,TMAX,8,,,E, +ITE00100554,17891214,TMIN,-13,,,E, +GM000010962,17891214,PRCP,0,,,E, +EZE00100082,17891215,TMAX,66,,,E, +EZE00100082,17891215,TMIN,15,,,E, +ITE00100554,17891215,TMAX,0,,,E, +ITE00100554,17891215,TMIN,-3,,,E, +GM000010962,17891215,PRCP,0,,,E, +EZE00100082,17891216,TMAX,47,,,E, +EZE00100082,17891216,TMIN,28,,,E, +ITE00100554,17891216,TMAX,13,,,E, +ITE00100554,17891216,TMIN,0,,,E, +GM000010962,17891216,PRCP,4,,,E, +EZE00100082,17891217,TMAX,42,,,E, +EZE00100082,17891217,TMIN,26,,,E, +ITE00100554,17891217,TMAX,0,,,E, +ITE00100554,17891217,TMIN,-15,,,E, +GM000010962,17891217,PRCP,6,,,E, +EZE00100082,17891218,TMAX,58,,,E, +EZE00100082,17891218,TMIN,26,,,E, +ITE00100554,17891218,TMAX,25,,,E, +ITE00100554,17891218,TMIN,-29,,,E, +GM000010962,17891218,PRCP,9,,,E, +EZE00100082,17891219,TMAX,53,,,E, +EZE00100082,17891219,TMIN,34,,,E, +ITE00100554,17891219,TMAX,15,,,E, +ITE00100554,17891219,TMIN,-31,,,E, +GM000010962,17891219,PRCP,0,,,E, +EZE00100082,17891220,TMAX,60,,,E, +EZE00100082,17891220,TMIN,34,,,E, +ITE00100554,17891220,TMAX,13,,,E, +ITE00100554,17891220,TMIN,-40,,,E, +GM000010962,17891220,PRCP,0,,,E, +EZE00100082,17891221,TMAX,71,,,E, +EZE00100082,17891221,TMIN,40,,,E, +ITE00100554,17891221,TMAX,9,,,E, +ITE00100554,17891221,TMIN,-34,,,E, +GM000010962,17891221,PRCP,0,,,E, +EZE00100082,17891222,TMAX,94,,,E, +EZE00100082,17891222,TMIN,40,,,E, +ITE00100554,17891222,TMAX,8,,,E, +ITE00100554,17891222,TMIN,-44,,,E, +GM000010962,17891222,PRCP,0,,,E, +EZE00100082,17891223,TMAX,105,,,E, +EZE00100082,17891223,TMIN,64,,,E, +ITE00100554,17891223,TMAX,6,,,E, +ITE00100554,17891223,TMIN,-34,,,E, +GM000010962,17891223,PRCP,0,,,E, +EZE00100082,17891224,TMAX,98,,,E, +EZE00100082,17891224,TMIN,38,,,E, +ITE00100554,17891224,TMAX,19,,,E, +ITE00100554,17891224,TMIN,0,,,E, +GM000010962,17891224,PRCP,0,,,E, +EZE00100082,17891225,TMAX,66,,,E, +EZE00100082,17891225,TMIN,37,,,E, +ITE00100554,17891225,TMAX,16,,,E, +ITE00100554,17891225,TMIN,8,,,E, +GM000010962,17891225,PRCP,0,,,E, +EZE00100082,17891226,TMAX,48,,,E, +EZE00100082,17891226,TMIN,30,,,E, +ITE00100554,17891226,TMAX,19,,,E, +ITE00100554,17891226,TMIN,8,,,E, +GM000010962,17891226,PRCP,7,,,E, +EZE00100082,17891227,TMAX,64,,,E, +EZE00100082,17891227,TMIN,20,,,E, +ITE00100554,17891227,TMAX,0,,,E, +ITE00100554,17891227,TMIN,-8,,,E, +GM000010962,17891227,PRCP,34,,,E, +EZE00100082,17891228,TMAX,63,,,E, +EZE00100082,17891228,TMIN,23,,,E, +ITE00100554,17891228,TMAX,15,,,E, +ITE00100554,17891228,TMIN,-15,,,E, +GM000010962,17891228,PRCP,0,,,E, +EZE00100082,17891229,TMAX,90,,,E, +EZE00100082,17891229,TMIN,57,,,E, +ITE00100554,17891229,TMAX,-3,,,E, +ITE00100554,17891229,TMIN,-19,,,E, +GM000010962,17891229,PRCP,6,,,E, +EZE00100082,17891230,TMAX,111,,,E, +EZE00100082,17891230,TMIN,86,,,E, +ITE00100554,17891230,TMAX,-19,,,E, +ITE00100554,17891230,TMIN,-28,,,E, +GM000010962,17891230,PRCP,0,,,E, +EZE00100082,17891231,TMAX,90,,,E, +EZE00100082,17891231,TMIN,24,,,E, +ITE00100554,17891231,TMAX,-4,,,E, +ITE00100554,17891231,TMIN,-29,,,E, +GM000010962,17891231,PRCP,0,,,E, +EZE00100082,17900101,TMAX,36,,,E, +EZE00100082,17900101,TMIN,8,,,E, +ITE00100554,17900101,TMAX,13,,,E, +ITE00100554,17900101,TMIN,-3,,,E, +GM000010962,17900101,PRCP,0,,,E, +EZE00100082,17900102,TMAX,41,,,E, +EZE00100082,17900102,TMIN,8,,,E, +ITE00100554,17900102,TMAX,25,,,E, +ITE00100554,17900102,TMIN,-15,,,E, +GM000010962,17900102,PRCP,9,,,E, +EZE00100082,17900103,TMAX,29,,,E, +EZE00100082,17900103,TMIN,-4,,,E, +ITE00100554,17900103,TMAX,16,,,E, +ITE00100554,17900103,TMIN,-16,,,E, +GM000010962,17900103,PRCP,0,,,E, +EZE00100082,17900104,TMAX,58,,,E, +EZE00100082,17900104,TMIN,29,,,E, +ITE00100554,17900104,TMAX,6,,,E, +ITE00100554,17900104,TMIN,-9,,,E, +GM000010962,17900104,PRCP,15,,,E, +EZE00100082,17900105,TMAX,41,,,E, +EZE00100082,17900105,TMIN,24,,,E, +ITE00100554,17900105,TMAX,9,,,E, +ITE00100554,17900105,TMIN,-4,,,E, +GM000010962,17900105,PRCP,5,,,E, +EZE00100082,17900106,TMAX,24,,,E, +EZE00100082,17900106,TMIN,0,,,E, +ITE00100554,17900106,TMAX,25,,,E, +ITE00100554,17900106,TMIN,3,,,E, +GM000010962,17900106,PRCP,0,,,E, +EZE00100082,17900107,TMAX,23,,,E, +EZE00100082,17900107,TMIN,13,,,E, +ITE00100554,17900107,TMAX,25,,,E, +ITE00100554,17900107,TMIN,-25,,,E, +GM000010962,17900107,PRCP,0,,,E, +EZE00100082,17900108,TMAX,48,,,E, +EZE00100082,17900108,TMIN,23,,,E, +ITE00100554,17900108,TMAX,40,,,E, +ITE00100554,17900108,TMIN,-9,,,E, +GM000010962,17900108,PRCP,9,,,E, +EZE00100082,17900109,TMAX,53,,,E, +EZE00100082,17900109,TMIN,37,,,E, +ITE00100554,17900109,TMAX,44,,,E, +ITE00100554,17900109,TMIN,-8,,,E, +GM000010962,17900109,PRCP,0,,,E, +EZE00100082,17900110,TMAX,43,,,E, +EZE00100082,17900110,TMIN,30,,,E, +ITE00100554,17900110,TMAX,13,,,E, +ITE00100554,17900110,TMIN,-3,,,E, +GM000010962,17900110,PRCP,0,,,E, +EZE00100082,17900111,TMAX,44,,,E, +EZE00100082,17900111,TMIN,13,,,E, +ITE00100554,17900111,TMAX,25,,,E, +ITE00100554,17900111,TMIN,-16,,,E, +GM000010962,17900111,PRCP,0,,,E, +EZE00100082,17900112,TMAX,58,,,E, +EZE00100082,17900112,TMIN,4,,,E, +ITE00100554,17900112,TMAX,29,,,E, +ITE00100554,17900112,TMIN,-19,,,E, +GM000010962,17900112,PRCP,0,,,E, +EZE00100082,17900113,TMAX,78,,,E, +EZE00100082,17900113,TMIN,57,,,E, +ITE00100554,17900113,TMAX,34,,,E, +ITE00100554,17900113,TMIN,-8,,,E, +GM000010962,17900113,PRCP,0,,,E, +EZE00100082,17900114,TMAX,68,,,E, +EZE00100082,17900114,TMIN,40,,,E, +ITE00100554,17900114,TMAX,38,,,E, +ITE00100554,17900114,TMIN,0,,,E, +GM000010962,17900114,PRCP,0,,,E, +EZE00100082,17900115,TMAX,55,,,E, +EZE00100082,17900115,TMIN,7,,,E, +ITE00100554,17900115,TMAX,40,,,E, +ITE00100554,17900115,TMIN,21,,,E, +GM000010962,17900115,PRCP,0,,,E, +EZE00100082,17900116,TMAX,27,,,E, +EZE00100082,17900116,TMIN,6,,,E, +ITE00100554,17900116,TMAX,15,,,E, +ITE00100554,17900116,TMIN,4,,,E, +GM000010962,17900116,PRCP,0,,,E, +EZE00100082,17900117,TMAX,24,,,E, +EZE00100082,17900117,TMIN,-20,,,E, +ITE00100554,17900117,TMAX,44,,,E, +ITE00100554,17900117,TMIN,-6,,,E, +GM000010962,17900117,PRCP,7,,,E, +EZE00100082,17900118,TMAX,-6,,,E, +EZE00100082,17900118,TMIN,-42,,,E, +ITE00100554,17900118,TMAX,34,,,E, +ITE00100554,17900118,TMIN,0,,,E, +GM000010962,17900118,PRCP,0,,,E, +EZE00100082,17900119,TMAX,13,,,E, +EZE00100082,17900119,TMIN,-27,,,E, +ITE00100554,17900119,TMAX,25,,,E, +ITE00100554,17900119,TMIN,0,,,E, +GM000010962,17900119,PRCP,0,,,E, +EZE00100082,17900120,TMAX,22,,,E, +EZE00100082,17900120,TMIN,-20,,,E, +ITE00100554,17900120,TMAX,19,,,E, +ITE00100554,17900120,TMIN,-15,,,E, +GM000010962,17900120,PRCP,0,,,E, +EZE00100082,17900121,TMAX,0,,,E, +EZE00100082,17900121,TMIN,-21,,,E, +ITE00100554,17900121,TMAX,19,,,E, +ITE00100554,17900121,TMIN,-34,,,E, +GM000010962,17900121,PRCP,0,,,E, +EZE00100082,17900122,TMAX,0,,,E, +EZE00100082,17900122,TMIN,-4,,,E, +ITE00100554,17900122,TMAX,19,,,E, +ITE00100554,17900122,TMIN,-28,,,E, +GM000010962,17900122,PRCP,0,,,E, +EZE00100082,17900123,TMAX,17,,,E, +EZE00100082,17900123,TMIN,-15,,,E, +ITE00100554,17900123,TMAX,19,,,E, +ITE00100554,17900123,TMIN,-19,,,E, +GM000010962,17900123,PRCP,17,,,E, +EZE00100082,17900124,TMAX,15,,,E, +EZE00100082,17900124,TMIN,-8,,,E, +ITE00100554,17900124,TMAX,28,,,E, +ITE00100554,17900124,TMIN,-16,,,E, +GM000010962,17900124,PRCP,33,,,E, +EZE00100082,17900125,TMAX,45,,,E, +EZE00100082,17900125,TMIN,6,,,E, +ITE00100554,17900125,TMAX,46,,,E, +ITE00100554,17900125,TMIN,-16,,,E, +GM000010962,17900125,PRCP,25,,,E, +EZE00100082,17900126,TMAX,39,,,E, +EZE00100082,17900126,TMIN,-34,,,E, +ITE00100554,17900126,TMAX,59,,,E, +ITE00100554,17900126,TMIN,-3,,,E, +GM000010962,17900126,PRCP,73,,,E, +EZE00100082,17900127,TMAX,-3,,,E, +EZE00100082,17900127,TMIN,-62,,,E, +ITE00100554,17900127,TMAX,3,,,E, +ITE00100554,17900127,TMIN,-3,,,E, +GM000010962,17900127,PRCP,0,,,E, +EZE00100082,17900128,TMAX,-26,,,E, +EZE00100082,17900128,TMIN,-44,,,E, +ITE00100554,17900128,TMAX,21,,,E, +ITE00100554,17900128,TMIN,-6,,,E, +GM000010962,17900128,PRCP,0,,,E, +EZE00100082,17900129,TMAX,44,,,E, +EZE00100082,17900129,TMIN,-44,,,E, +ITE00100554,17900129,TMAX,4,,,E, +ITE00100554,17900129,TMIN,-8,,,E, +GM000010962,17900129,PRCP,9,,,E, +EZE00100082,17900130,TMAX,46,,,E, +EZE00100082,17900130,TMIN,7,,,E, +ITE00100554,17900130,TMAX,4,,,E, +ITE00100554,17900130,TMIN,0,,,E, +GM000010962,17900130,PRCP,7,,,E, +EZE00100082,17900131,TMAX,26,,,E, +EZE00100082,17900131,TMIN,10,,,E, +ITE00100554,17900131,TMAX,-8,,,E, +ITE00100554,17900131,TMIN,-19,,,E, +GM000010962,17900131,PRCP,15,,,E, +EZE00100082,17900201,TMAX,23,,,E, +EZE00100082,17900201,TMIN,1,,,E, +ITE00100554,17900201,TMAX,0,,,E, +ITE00100554,17900201,TMIN,-34,,,E, +GM000010962,17900201,PRCP,15,,,E, +EZE00100082,17900202,TMAX,49,,,E, +EZE00100082,17900202,TMIN,4,,,E, +ITE00100554,17900202,TMAX,-8,,,E, +ITE00100554,17900202,TMIN,-25,,,E, +GM000010962,17900202,PRCP,5,,,E, +EZE00100082,17900203,TMAX,71,,,E, +EZE00100082,17900203,TMIN,32,,,E, +ITE00100554,17900203,TMAX,4,,,E, +ITE00100554,17900203,TMIN,-40,,,E, +GM000010962,17900203,PRCP,8,,,E, +EZE00100082,17900204,TMAX,80,,,E, +EZE00100082,17900204,TMIN,49,,,E, +ITE00100554,17900204,TMAX,40,,,E, +ITE00100554,17900204,TMIN,-16,,,E, +GM000010962,17900204,PRCP,3,,,E, +EZE00100082,17900205,TMAX,62,,,E, +EZE00100082,17900205,TMIN,44,,,E, +ITE00100554,17900205,TMAX,65,,,E, +ITE00100554,17900205,TMIN,-8,,,E, +GM000010962,17900205,PRCP,0,,,E, +EZE00100082,17900206,TMAX,75,,,E, +EZE00100082,17900206,TMIN,40,,,E, +ITE00100554,17900206,TMAX,95,,,E, +ITE00100554,17900206,TMIN,3,,,E, +GM000010962,17900206,PRCP,0,,,E, +EZE00100082,17900207,TMAX,91,,,E, +EZE00100082,17900207,TMIN,42,,,E, +ITE00100554,17900207,TMAX,100,,,E, +ITE00100554,17900207,TMIN,34,,,E, +GM000010962,17900207,PRCP,8,,,E, +EZE00100082,17900208,TMAX,75,,,E, +EZE00100082,17900208,TMIN,54,,,E, +ITE00100554,17900208,TMAX,106,,,E, +ITE00100554,17900208,TMIN,13,,,E, +GM000010962,17900208,PRCP,0,,,E, +EZE00100082,17900209,TMAX,59,,,E, +EZE00100082,17900209,TMIN,29,,,E, +ITE00100554,17900209,TMAX,106,,,E, +ITE00100554,17900209,TMIN,46,,,E, +GM000010962,17900209,PRCP,0,,,E, +EZE00100082,17900210,TMAX,29,,,E, +EZE00100082,17900210,TMIN,-27,,,E, +ITE00100554,17900210,TMAX,104,,,E, +ITE00100554,17900210,TMIN,31,,,E, +GM000010962,17900210,PRCP,11,,,E, +EZE00100082,17900211,TMAX,-6,,,E, +EZE00100082,17900211,TMIN,-32,,,E, +ITE00100554,17900211,TMAX,69,,,E, +ITE00100554,17900211,TMIN,46,,,E, +GM000010962,17900211,PRCP,5,,,E, +EZE00100082,17900212,TMAX,50,,,E, +EZE00100082,17900212,TMIN,-7,,,E, +ITE00100554,17900212,TMAX,94,,,E, +ITE00100554,17900212,TMIN,3,,,E, +GM000010962,17900212,PRCP,10,,,E, +EZE00100082,17900213,TMAX,85,,,E, +EZE00100082,17900213,TMIN,48,,,E, +ITE00100554,17900213,TMAX,95,,,E, +ITE00100554,17900213,TMIN,13,,,E, +GM000010962,17900213,PRCP,3,,,E, +EZE00100082,17900214,TMAX,74,,,E, +EZE00100082,17900214,TMIN,28,,,E, +ITE00100554,17900214,TMAX,103,,,E, +ITE00100554,17900214,TMIN,20,,,E, +GM000010962,17900214,PRCP,0,,,E, +EZE00100082,17900215,TMAX,70,,,E, +EZE00100082,17900215,TMIN,14,,,E, +ITE00100554,17900215,TMAX,103,,,E, +ITE00100554,17900215,TMIN,31,,,E, +GM000010962,17900215,PRCP,0,,,E, +EZE00100082,17900216,TMAX,73,,,E, +EZE00100082,17900216,TMIN,20,,,E, +ITE00100554,17900216,TMAX,84,,,E, +ITE00100554,17900216,TMIN,34,,,E, +GM000010962,17900216,PRCP,0,,,E, +EZE00100082,17900217,TMAX,59,,,E, +EZE00100082,17900217,TMIN,7,,,E, +ITE00100554,17900217,TMAX,109,,,E, +ITE00100554,17900217,TMIN,46,,,E, +GM000010962,17900217,PRCP,0,,,E, +EZE00100082,17900218,TMAX,73,,,E, +EZE00100082,17900218,TMIN,32,,,E, +ITE00100554,17900218,TMAX,109,,,E, +ITE00100554,17900218,TMIN,59,,,E, +GM000010962,17900218,PRCP,8,,,E, +EZE00100082,17900219,TMAX,87,,,E, +EZE00100082,17900219,TMIN,32,,,E, +ITE00100554,17900219,TMAX,100,,,E, +ITE00100554,17900219,TMIN,66,,,E, +GM000010962,17900219,PRCP,0,,,E, +EZE00100082,17900220,TMAX,81,,,E, +EZE00100082,17900220,TMIN,9,,,E, +ITE00100554,17900220,TMAX,100,,,E, +ITE00100554,17900220,TMIN,31,,,E, +GM000010962,17900220,PRCP,0,,,E, +EZE00100082,17900221,TMAX,39,,,E, +EZE00100082,17900221,TMIN,-3,,,E, +ITE00100554,17900221,TMAX,100,,,E, +ITE00100554,17900221,TMIN,31,,,E, +GM000010962,17900221,PRCP,0,,,E, +EZE00100082,17900222,TMAX,62,,,E, +EZE00100082,17900222,TMIN,-17,,,E, +ITE00100554,17900222,TMAX,109,,,E, +ITE00100554,17900222,TMIN,29,,,E, +GM000010962,17900222,PRCP,0,,,E, +EZE00100082,17900223,TMAX,39,,,E, +EZE00100082,17900223,TMIN,5,,,E, +ITE00100554,17900223,TMAX,94,,,E, +ITE00100554,17900223,TMIN,66,,,E, +GM000010962,17900223,PRCP,0,,,E, +EZE00100082,17900224,TMAX,33,,,E, +EZE00100082,17900224,TMIN,10,,,E, +ITE00100554,17900224,TMAX,83,,,E, +ITE00100554,17900224,TMIN,70,,,E, +GM000010962,17900224,PRCP,0,,,E, +EZE00100082,17900225,TMAX,80,,,E, +EZE00100082,17900225,TMIN,13,,,E, +ITE00100554,17900225,TMAX,113,,,E, +ITE00100554,17900225,TMIN,56,,,E, +GM000010962,17900225,PRCP,0,,,E, +EZE00100082,17900226,TMAX,115,,,E, +EZE00100082,17900226,TMIN,45,,,E, +ITE00100554,17900226,TMAX,125,,,E, +ITE00100554,17900226,TMIN,59,,,E, +GM000010962,17900226,PRCP,0,,,E, +EZE00100082,17900227,TMAX,85,,,E, +EZE00100082,17900227,TMIN,48,,,E, +ITE00100554,17900227,TMAX,119,,,E, +ITE00100554,17900227,TMIN,69,,,E, +GM000010962,17900227,PRCP,6,,,E, +EZE00100082,17900228,TMAX,77,,,E, +EZE00100082,17900228,TMIN,28,,,E, +ITE00100554,17900228,TMAX,125,,,E, +ITE00100554,17900228,TMIN,56,,,E, +GM000010962,17900228,PRCP,3,,,E, +EZE00100082,17900301,TMAX,44,,,E, +EZE00100082,17900301,TMIN,14,,,E, +ITE00100554,17900301,TMAX,144,,,E, +ITE00100554,17900301,TMIN,88,,,E, +GM000010962,17900301,PRCP,15,,,E, +EZE00100082,17900302,TMAX,21,,,E, +EZE00100082,17900302,TMIN,-3,,,E, +ITE00100554,17900302,TMAX,125,,,E, +ITE00100554,17900302,TMIN,44,,,E, +GM000010962,17900302,PRCP,10,,,E, +EZE00100082,17900303,TMAX,23,,,E, +EZE00100082,17900303,TMIN,-12,,,E, +ITE00100554,17900303,TMAX,81,,,E, +ITE00100554,17900303,TMIN,41,,,E, +GM000010962,17900303,PRCP,13,,,E, +EZE00100082,17900304,TMAX,62,,,E, +EZE00100082,17900304,TMIN,17,,,E, +ITE00100554,17900304,TMAX,75,,,E, +ITE00100554,17900304,TMIN,31,,,E, +GM000010962,17900304,PRCP,10,,,E, +EZE00100082,17900305,TMAX,35,,,E, +EZE00100082,17900305,TMIN,-11,,,E, +ITE00100554,17900305,TMAX,98,,,E, +ITE00100554,17900305,TMIN,19,,,E, +GM000010962,17900305,PRCP,15,,,E, +EZE00100082,17900306,TMAX,29,,,E, +EZE00100082,17900306,TMIN,-11,,,E, +ITE00100554,17900306,TMAX,81,,,E, +ITE00100554,17900306,TMIN,33,,,E, +GM000010962,17900306,PRCP,11,,,E, +EZE00100082,17900307,TMAX,49,,,E, +EZE00100082,17900307,TMIN,-8,,,E, +ITE00100554,17900307,TMAX,94,,,E, +ITE00100554,17900307,TMIN,15,,,E, +GM000010962,17900307,PRCP,0,,,E, +EZE00100082,17900308,TMAX,62,,,E, +EZE00100082,17900308,TMIN,10,,,E, +ITE00100554,17900308,TMAX,116,,,E, +ITE00100554,17900308,TMIN,29,,,E, +GM000010962,17900308,PRCP,0,,,E, +EZE00100082,17900309,TMAX,96,,,E, +EZE00100082,17900309,TMIN,17,,,E, +ITE00100554,17900309,TMAX,109,,,E, +ITE00100554,17900309,TMIN,38,,,E, +GM000010962,17900309,PRCP,0,,,E, +EZE00100082,17900310,TMAX,117,,,E, +EZE00100082,17900310,TMIN,17,,,E, +ITE00100554,17900310,TMAX,109,,,E, +ITE00100554,17900310,TMIN,46,,,E, +GM000010962,17900310,PRCP,0,,,E, +EZE00100082,17900311,TMAX,87,,,E, +EZE00100082,17900311,TMIN,34,,,E, +ITE00100554,17900311,TMAX,115,,,E, +ITE00100554,17900311,TMIN,63,,,E, +GM000010962,17900311,PRCP,5,,,E, +EZE00100082,17900312,TMAX,94,,,E, +EZE00100082,17900312,TMIN,27,,,E, +ITE00100554,17900312,TMAX,119,,,E, +ITE00100554,17900312,TMIN,45,,,E, +GM000010962,17900312,PRCP,0,,,E, +EZE00100082,17900313,TMAX,98,,,E, +EZE00100082,17900313,TMIN,12,,,E, +ITE00100554,17900313,TMAX,125,,,E, +ITE00100554,17900313,TMIN,53,,,E, +GM000010962,17900313,PRCP,0,,,E, +EZE00100082,17900314,TMAX,100,,,E, +EZE00100082,17900314,TMIN,24,,,E, +ITE00100554,17900314,TMAX,125,,,E, +ITE00100554,17900314,TMIN,34,,,E, +GM000010962,17900314,PRCP,0,,,E, +EZE00100082,17900315,TMAX,58,,,E, +EZE00100082,17900315,TMIN,27,,,E, +ITE00100554,17900315,TMAX,125,,,E, +ITE00100554,17900315,TMIN,50,,,E, +GM000010962,17900315,PRCP,26,,,E, +EZE00100082,17900316,TMAX,66,,,E, +EZE00100082,17900316,TMIN,18,,,E, +ITE00100554,17900316,TMAX,100,,,E, +ITE00100554,17900316,TMIN,29,,,E, +GM000010962,17900316,PRCP,15,,,E, +EZE00100082,17900317,TMAX,81,,,E, +EZE00100082,17900317,TMIN,12,,,E, +ITE00100554,17900317,TMAX,100,,,E, +ITE00100554,17900317,TMIN,46,,,E, +GM000010962,17900317,PRCP,0,,,E, +EZE00100082,17900318,TMAX,70,,,E, +EZE00100082,17900318,TMIN,25,,,E, +ITE00100554,17900318,TMAX,113,,,E, +ITE00100554,17900318,TMIN,25,,,E, +GM000010962,17900318,PRCP,0,,,E, +EZE00100082,17900319,TMAX,79,,,E, +EZE00100082,17900319,TMIN,29,,,E, +ITE00100554,17900319,TMAX,125,,,E, +ITE00100554,17900319,TMIN,69,,,E, +GM000010962,17900319,PRCP,18,,,E, +EZE00100082,17900320,TMAX,97,,,E, +EZE00100082,17900320,TMIN,13,,,E, +ITE00100554,17900320,TMAX,100,,,E, +ITE00100554,17900320,TMIN,63,,,E, +GM000010962,17900320,PRCP,0,,,E, +EZE00100082,17900321,TMAX,110,,,E, +EZE00100082,17900321,TMIN,10,,,E, +ITE00100554,17900321,TMAX,100,,,E, +ITE00100554,17900321,TMIN,63,,,E, +GM000010962,17900321,PRCP,0,,,E, +EZE00100082,17900322,TMAX,111,,,E, +EZE00100082,17900322,TMIN,15,,,E, +ITE00100554,17900322,TMAX,103,,,E, +ITE00100554,17900322,TMIN,65,,,E, +GM000010962,17900322,PRCP,0,,,E, +EZE00100082,17900323,TMAX,133,,,E, +EZE00100082,17900323,TMIN,40,,,E, +ITE00100554,17900323,TMAX,125,,,E, +ITE00100554,17900323,TMIN,38,,,E, +GM000010962,17900323,PRCP,0,,,E, +EZE00100082,17900324,TMAX,149,,,E, +EZE00100082,17900324,TMIN,46,,,E, +ITE00100554,17900324,TMAX,125,,,E, +ITE00100554,17900324,TMIN,46,,,E, +GM000010962,17900324,PRCP,0,,,E, +EZE00100082,17900325,TMAX,160,,,E, +EZE00100082,17900325,TMIN,51,,,E, +ITE00100554,17900325,TMAX,150,,,E, +ITE00100554,17900325,TMIN,59,,,E, +GM000010962,17900325,PRCP,0,,,E, +EZE00100082,17900326,TMAX,171,,,E, +EZE00100082,17900326,TMIN,58,,,E, +ITE00100554,17900326,TMAX,163,,,E, +ITE00100554,17900326,TMIN,81,,,E, +GM000010962,17900326,PRCP,0,,,E, +EZE00100082,17900327,TMAX,183,,,E, +EZE00100082,17900327,TMIN,52,,,E, +ITE00100554,17900327,TMAX,163,,,E, +ITE00100554,17900327,TMIN,56,,,E, +GM000010962,17900327,PRCP,0,,,E, +EZE00100082,17900328,TMAX,143,,,E, +EZE00100082,17900328,TMIN,72,,,E, +ITE00100554,17900328,TMAX,175,,,E, +ITE00100554,17900328,TMIN,78,,,E, +GM000010962,17900328,PRCP,0,,,E, +EZE00100082,17900329,TMAX,109,,,E, +EZE00100082,17900329,TMIN,27,,,E, +ITE00100554,17900329,TMAX,138,,,E, +ITE00100554,17900329,TMIN,79,,,E, +GM000010962,17900329,PRCP,0,,,E, +EZE00100082,17900330,TMAX,103,,,E, +EZE00100082,17900330,TMIN,18,,,E, +ITE00100554,17900330,TMAX,138,,,E, +ITE00100554,17900330,TMIN,50,,,E, +GM000010962,17900330,PRCP,0,,,E, +EZE00100082,17900331,TMAX,55,,,E, +EZE00100082,17900331,TMIN,-32,,,E, +ITE00100554,17900331,TMAX,125,,,E, +ITE00100554,17900331,TMIN,53,,,E, +GM000010962,17900331,PRCP,0,,,E, +EZE00100082,17900401,TMAX,36,,,E, +EZE00100082,17900401,TMIN,-43,,,E, +ITE00100554,17900401,TMAX,56,,,E, +ITE00100554,17900401,TMIN,50,,,E, +GM000010962,17900401,PRCP,3,,,E, +EZE00100082,17900402,TMAX,43,,,E, +EZE00100082,17900402,TMIN,-35,,,E, +ITE00100554,17900402,TMAX,100,,,E, +ITE00100554,17900402,TMIN,0,,,E, +GM000010962,17900402,PRCP,0,,,E, +EZE00100082,17900403,TMAX,78,,,E, +EZE00100082,17900403,TMIN,-16,,,E, +ITE00100554,17900403,TMAX,65,,,E, +ITE00100554,17900403,TMIN,9,,,E, +GM000010962,17900403,PRCP,13,,,E, +EZE00100082,17900404,TMAX,51,,,E, +EZE00100082,17900404,TMIN,2,,,E, +ITE00100554,17900404,TMAX,95,,,E, +ITE00100554,17900404,TMIN,25,,,E, +GM000010962,17900404,PRCP,7,,,E, +EZE00100082,17900405,TMAX,28,,,E, +EZE00100082,17900405,TMIN,-19,,,E, +ITE00100554,17900405,TMAX,113,,,E, +ITE00100554,17900405,TMIN,19,,,E, +GM000010962,17900405,PRCP,0,,,E, +EZE00100082,17900406,TMAX,56,,,E, +EZE00100082,17900406,TMIN,-38,,,E, +ITE00100554,17900406,TMAX,100,,,E, +ITE00100554,17900406,TMIN,50,,,E, +GM000010962,17900406,PRCP,0,,,E, +EZE00100082,17900407,TMAX,88,,,E, +EZE00100082,17900407,TMIN,-22,,,E, +ITE00100554,17900407,TMAX,100,,,E, +ITE00100554,17900407,TMIN,53,,,E, +GM000010962,17900407,PRCP,0,,,E, +EZE00100082,17900408,TMAX,96,,,E, +EZE00100082,17900408,TMIN,-6,,,E, +ITE00100554,17900408,TMAX,88,,,E, +ITE00100554,17900408,TMIN,60,,,E, +GM000010962,17900408,PRCP,0,,,E, +EZE00100082,17900409,TMAX,132,,,E, +EZE00100082,17900409,TMIN,11,,,E, +ITE00100554,17900409,TMAX,96,,,E, +ITE00100554,17900409,TMIN,63,,,E, +GM000010962,17900409,PRCP,0,,,E, +EZE00100082,17900410,TMAX,128,,,E, +EZE00100082,17900410,TMIN,59,,,E, +ITE00100554,17900410,TMAX,88,,,E, +ITE00100554,17900410,TMIN,63,,,E, +GM000010962,17900410,PRCP,4,,,E, +EZE00100082,17900411,TMAX,182,,,E, +EZE00100082,17900411,TMIN,70,,,E, +ITE00100554,17900411,TMAX,106,,,E, +ITE00100554,17900411,TMIN,81,,,E, +GM000010962,17900411,PRCP,0,,,E, +EZE00100082,17900412,TMAX,175,,,E, +EZE00100082,17900412,TMIN,89,,,E, +ITE00100554,17900412,TMAX,103,,,E, +ITE00100554,17900412,TMIN,100,,,E, +GM000010962,17900412,PRCP,0,,,E, +EZE00100082,17900413,TMAX,180,,,E, +EZE00100082,17900413,TMIN,71,,,E, +ITE00100554,17900413,TMAX,144,,,E, +ITE00100554,17900413,TMIN,94,,,E, +GM000010962,17900413,PRCP,3,,,E, +EZE00100082,17900414,TMAX,173,,,E, +EZE00100082,17900414,TMIN,68,,,E, +ITE00100554,17900414,TMAX,106,,,E, +ITE00100554,17900414,TMIN,100,,,E, +GM000010962,17900414,PRCP,0,,,E, +EZE00100082,17900415,TMAX,137,,,E, +EZE00100082,17900415,TMIN,80,,,E, +ITE00100554,17900415,TMAX,113,,,E, +ITE00100554,17900415,TMIN,106,,,E, +GM000010962,17900415,PRCP,4,,,E, +EZE00100082,17900416,TMAX,184,,,E, +EZE00100082,17900416,TMIN,66,,,E, +ITE00100554,17900416,TMAX,165,,,E, +ITE00100554,17900416,TMIN,106,,,E, +GM000010962,17900416,PRCP,0,,,E, +EZE00100082,17900417,TMAX,112,,,E, +EZE00100082,17900417,TMIN,60,,,E, +ITE00100554,17900417,TMAX,181,,,E, +ITE00100554,17900417,TMIN,109,,,E, +GM000010962,17900417,PRCP,45,,,E, +EZE00100082,17900418,TMAX,90,,,E, +EZE00100082,17900418,TMIN,27,,,E, +ITE00100554,17900418,TMAX,150,,,E, +ITE00100554,17900418,TMIN,119,,,E, +GM000010962,17900418,PRCP,59,,,E, +EZE00100082,17900419,TMAX,46,,,E, +EZE00100082,17900419,TMIN,15,,,E, +ITE00100554,17900419,TMAX,146,,,E, +ITE00100554,17900419,TMIN,94,,,E, +GM000010962,17900419,PRCP,7,,,E, +EZE00100082,17900420,TMAX,42,,,E, +EZE00100082,17900420,TMIN,4,,,E, +ITE00100554,17900420,TMAX,144,,,E, +ITE00100554,17900420,TMIN,94,,,E, +GM000010962,17900420,PRCP,4,,,E, +EZE00100082,17900421,TMAX,64,,,E, +EZE00100082,17900421,TMIN,-4,,,E, +ITE00100554,17900421,TMAX,138,,,E, +ITE00100554,17900421,TMIN,88,,,E, +GM000010962,17900421,PRCP,0,,,E, +EZE00100082,17900422,TMAX,93,,,E, +EZE00100082,17900422,TMIN,16,,,E, +ITE00100554,17900422,TMAX,144,,,E, +ITE00100554,17900422,TMIN,96,,,E, +GM000010962,17900422,PRCP,0,,,E, +EZE00100082,17900423,TMAX,122,,,E, +EZE00100082,17900423,TMIN,37,,,E, +ITE00100554,17900423,TMAX,146,,,E, +ITE00100554,17900423,TMIN,94,,,E, +GM000010962,17900423,PRCP,5,,,E, +EZE00100082,17900424,TMAX,175,,,E, +EZE00100082,17900424,TMIN,68,,,E, +ITE00100554,17900424,TMAX,156,,,E, +ITE00100554,17900424,TMIN,106,,,E, +GM000010962,17900424,PRCP,6,,,E, +EZE00100082,17900425,TMAX,174,,,E, +EZE00100082,17900425,TMIN,67,,,E, +ITE00100554,17900425,TMAX,164,,,E, +ITE00100554,17900425,TMIN,106,,,E, +GM000010962,17900425,PRCP,18,,,E, +EZE00100082,17900426,TMAX,182,,,E, +EZE00100082,17900426,TMIN,71,,,E, +ITE00100554,17900426,TMAX,171,,,E, +ITE00100554,17900426,TMIN,106,,,E, +GM000010962,17900426,PRCP,0,,,E, +EZE00100082,17900427,TMAX,198,,,E, +EZE00100082,17900427,TMIN,80,,,E, +ITE00100554,17900427,TMAX,178,,,E, +ITE00100554,17900427,TMIN,100,,,E, +GM000010962,17900427,PRCP,0,,,E, +EZE00100082,17900428,TMAX,166,,,E, +EZE00100082,17900428,TMIN,90,,,E, +ITE00100554,17900428,TMAX,144,,,E, +ITE00100554,17900428,TMIN,131,,,E, +GM000010962,17900428,PRCP,0,,,E, +EZE00100082,17900429,TMAX,180,,,E, +EZE00100082,17900429,TMIN,90,,,E, +ITE00100554,17900429,TMAX,194,,,E, +ITE00100554,17900429,TMIN,134,,,E, +GM000010962,17900429,PRCP,0,,,E, +EZE00100082,17900430,TMAX,148,,,E, +EZE00100082,17900430,TMIN,117,,,E, +ITE00100554,17900430,TMAX,196,,,E, +ITE00100554,17900430,TMIN,144,,,E, +GM000010962,17900430,PRCP,17,,,E, +EZE00100082,17900501,TMAX,188,,,E, +EZE00100082,17900501,TMIN,104,,,E, +ITE00100554,17900501,TMAX,200,,,E, +ITE00100554,17900501,TMIN,144,,,E, +GM000010962,17900501,PRCP,116,,,E, +EZE00100082,17900502,TMAX,205,,,E, +EZE00100082,17900502,TMIN,90,,,E, +ITE00100554,17900502,TMAX,175,,,E, +ITE00100554,17900502,TMIN,138,,,E, +GM000010962,17900502,PRCP,0,,,E, +EZE00100082,17900503,TMAX,222,,,E, +EZE00100082,17900503,TMIN,133,,,E, +ITE00100554,17900503,TMAX,188,,,E, +ITE00100554,17900503,TMIN,138,,,E, +GM000010962,17900503,PRCP,0,,,E, +EZE00100082,17900504,TMAX,241,,,E, +EZE00100082,17900504,TMIN,128,,,E, +ITE00100554,17900504,TMAX,203,,,E, +ITE00100554,17900504,TMIN,159,,,E, +GM000010962,17900504,PRCP,0,,,E, +EZE00100082,17900505,TMAX,202,,,E, +EZE00100082,17900505,TMIN,142,,,E, +ITE00100554,17900505,TMAX,238,,,E, +ITE00100554,17900505,TMIN,150,,,E, +GM000010962,17900505,PRCP,35,,,E, +EZE00100082,17900506,TMAX,206,,,E, +EZE00100082,17900506,TMIN,127,,,E, +ITE00100554,17900506,TMAX,213,,,E, +ITE00100554,17900506,TMIN,131,,,E, +GM000010962,17900506,PRCP,69,,,E, +EZE00100082,17900507,TMAX,222,,,E, +EZE00100082,17900507,TMIN,135,,,E, +ITE00100554,17900507,TMAX,138,,,E, +ITE00100554,17900507,TMIN,131,,,E, +GM000010962,17900507,PRCP,93,,,E, +EZE00100082,17900508,TMAX,169,,,E, +EZE00100082,17900508,TMIN,135,,,E, +ITE00100554,17900508,TMAX,138,,,E, +ITE00100554,17900508,TMIN,125,,,E, +GM000010962,17900508,PRCP,72,,,E, +EZE00100082,17900509,TMAX,164,,,E, +EZE00100082,17900509,TMIN,132,,,E, +ITE00100554,17900509,TMAX,175,,,E, +ITE00100554,17900509,TMIN,128,,,E, +GM000010962,17900509,PRCP,79,,,E, +EZE00100082,17900510,TMAX,189,,,E, +EZE00100082,17900510,TMIN,101,,,E, +ITE00100554,17900510,TMAX,194,,,E, +ITE00100554,17900510,TMIN,131,,,E, +GM000010962,17900510,PRCP,17,,,E, +EZE00100082,17900511,TMAX,163,,,E, +EZE00100082,17900511,TMIN,102,,,E, +ITE00100554,17900511,TMAX,213,,,E, +ITE00100554,17900511,TMIN,134,,,E, +GM000010962,17900511,PRCP,0,,,E, +EZE00100082,17900512,TMAX,152,,,E, +EZE00100082,17900512,TMIN,90,,,E, +ITE00100554,17900512,TMAX,206,,,E, +ITE00100554,17900512,TMIN,144,,,E, +GM000010962,17900512,PRCP,0,,,E, +EZE00100082,17900513,TMAX,180,,,E, +EZE00100082,17900513,TMIN,107,,,E, +ITE00100554,17900513,TMAX,181,,,E, +ITE00100554,17900513,TMIN,144,,,E, +GM000010962,17900513,PRCP,2,,,E, +EZE00100082,17900514,TMAX,170,,,E, +EZE00100082,17900514,TMIN,88,,,E, +ITE00100554,17900514,TMAX,200,,,E, +ITE00100554,17900514,TMIN,150,,,E, +GM000010962,17900514,PRCP,0,,,E, +EZE00100082,17900515,TMAX,194,,,E, +EZE00100082,17900515,TMIN,96,,,E, +ITE00100554,17900515,TMAX,200,,,E, +ITE00100554,17900515,TMIN,146,,,E, +GM000010962,17900515,PRCP,0,,,E, +EZE00100082,17900516,TMAX,169,,,E, +EZE00100082,17900516,TMIN,107,,,E, +ITE00100554,17900516,TMAX,196,,,E, +ITE00100554,17900516,TMIN,159,,,E, +GM000010962,17900516,PRCP,0,,,E, +EZE00100082,17900517,TMAX,185,,,E, +EZE00100082,17900517,TMIN,96,,,E, +ITE00100554,17900517,TMAX,165,,,E, +ITE00100554,17900517,TMIN,156,,,E, +GM000010962,17900517,PRCP,0,,,E, +EZE00100082,17900518,TMAX,207,,,E, +EZE00100082,17900518,TMIN,95,,,E, +ITE00100554,17900518,TMAX,225,,,E, +ITE00100554,17900518,TMIN,163,,,E, +GM000010962,17900518,PRCP,15,,,E, +EZE00100082,17900519,TMAX,210,,,E, +EZE00100082,17900519,TMIN,123,,,E, +ITE00100554,17900519,TMAX,213,,,E, +ITE00100554,17900519,TMIN,153,,,E, +GM000010962,17900519,PRCP,190,,,E, +EZE00100082,17900520,TMAX,222,,,E, +EZE00100082,17900520,TMIN,120,,,E, +ITE00100554,17900520,TMAX,219,,,E, +ITE00100554,17900520,TMIN,156,,,E, +GM000010962,17900520,PRCP,69,,,E, +EZE00100082,17900521,TMAX,190,,,E, +EZE00100082,17900521,TMIN,110,,,E, +ITE00100554,17900521,TMAX,225,,,E, +ITE00100554,17900521,TMIN,150,,,E, +GM000010962,17900521,PRCP,211,,,E, +EZE00100082,17900522,TMAX,174,,,E, +EZE00100082,17900522,TMIN,107,,,E, +ITE00100554,17900522,TMAX,231,,,E, +ITE00100554,17900522,TMIN,163,,,E, +GM000010962,17900522,PRCP,3,,,E, +EZE00100082,17900523,TMAX,204,,,E, +EZE00100082,17900523,TMIN,104,,,E, +ITE00100554,17900523,TMAX,244,,,E, +ITE00100554,17900523,TMIN,175,,,E, +GM000010962,17900523,PRCP,11,,,E, +EZE00100082,17900524,TMAX,245,,,E, +EZE00100082,17900524,TMIN,151,,,E, +ITE00100554,17900524,TMAX,254,,,E, +ITE00100554,17900524,TMIN,175,,,E, +GM000010962,17900524,PRCP,0,,,E, +EZE00100082,17900525,TMAX,277,,,E, +EZE00100082,17900525,TMIN,168,,,E, +ITE00100554,17900525,TMAX,265,,,E, +ITE00100554,17900525,TMIN,181,,,E, +GM000010962,17900525,PRCP,0,,,E, +EZE00100082,17900526,TMAX,266,,,E, +EZE00100082,17900526,TMIN,163,,,E, +ITE00100554,17900526,TMAX,266,,,E, +ITE00100554,17900526,TMIN,190,,,E, +GM000010962,17900526,PRCP,0,,,E, +EZE00100082,17900527,TMAX,284,,,E, +EZE00100082,17900527,TMIN,179,,,E, +ITE00100554,17900527,TMAX,275,,,E, +ITE00100554,17900527,TMIN,203,,,E, +GM000010962,17900527,PRCP,0,,,E, +EZE00100082,17900528,TMAX,286,,,E, +EZE00100082,17900528,TMIN,177,,,E, +ITE00100554,17900528,TMAX,278,,,E, +ITE00100554,17900528,TMIN,184,,,E, +GM000010962,17900528,PRCP,0,,,E, +EZE00100082,17900529,TMAX,254,,,E, +EZE00100082,17900529,TMIN,165,,,E, +ITE00100554,17900529,TMAX,288,,,E, +ITE00100554,17900529,TMIN,190,,,E, +GM000010962,17900529,PRCP,2,,,E, +EZE00100082,17900530,TMAX,242,,,E, +EZE00100082,17900530,TMIN,147,,,E, +ITE00100554,17900530,TMAX,263,,,E, +ITE00100554,17900530,TMIN,195,,,E, +GM000010962,17900530,PRCP,95,,,E, +EZE00100082,17900531,TMAX,245,,,E, +EZE00100082,17900531,TMIN,127,,,E, +ITE00100554,17900531,TMAX,250,,,E, +ITE00100554,17900531,TMIN,203,,I,E, +GM000010962,17900531,PRCP,170,,,E, +EZE00100082,17900601,TMAX,222,,,E, +EZE00100082,17900601,TMIN,107,,,E, +ITE00100554,17900601,TMAX,181,,I,E, +ITE00100554,17900601,TMIN,178,,,E, +GM000010962,17900601,PRCP,64,,,E, +EZE00100082,17900602,TMAX,226,,,E, +EZE00100082,17900602,TMIN,114,,,E, +ITE00100554,17900602,TMAX,238,,,E, +ITE00100554,17900602,TMIN,175,,,E, +GM000010962,17900602,PRCP,5,,,E, +EZE00100082,17900603,TMAX,256,,,E, +EZE00100082,17900603,TMIN,130,,,E, +ITE00100554,17900603,TMAX,240,,,E, +ITE00100554,17900603,TMIN,188,,,E, +GM000010962,17900603,PRCP,0,,,E, +EZE00100082,17900604,TMAX,265,,,E, +EZE00100082,17900604,TMIN,135,,,E, +ITE00100554,17900604,TMAX,263,,,E, +ITE00100554,17900604,TMIN,166,,,E, +GM000010962,17900604,PRCP,0,,,E, +EZE00100082,17900605,TMAX,185,,,E, +EZE00100082,17900605,TMIN,121,,,E, +ITE00100554,17900605,TMAX,263,,,E, +ITE00100554,17900605,TMIN,188,,,E, +GM000010962,17900605,PRCP,210,,,E, +EZE00100082,17900606,TMAX,202,,,E, +EZE00100082,17900606,TMIN,117,,,E, +ITE00100554,17900606,TMAX,263,,,E, +ITE00100554,17900606,TMIN,163,,,E, +GM000010962,17900606,PRCP,0,,,E, +EZE00100082,17900607,TMAX,202,,,E, +EZE00100082,17900607,TMIN,98,,,E, +ITE00100554,17900607,TMAX,238,,,E, +ITE00100554,17900607,TMIN,166,,,E, +GM000010962,17900607,PRCP,7,,,E, +EZE00100082,17900608,TMAX,193,,,E, +EZE00100082,17900608,TMIN,140,,,E, +ITE00100554,17900608,TMAX,238,,,E, +ITE00100554,17900608,TMIN,178,,,E, +GM000010962,17900608,PRCP,0,,,E, +EZE00100082,17900609,TMAX,257,,,E, +EZE00100082,17900609,TMIN,131,,,E, +ITE00100554,17900609,TMAX,263,,,E, +ITE00100554,17900609,TMIN,166,,,E, +GM000010962,17900609,PRCP,0,,,E, +EZE00100082,17900610,TMAX,288,,,E, +EZE00100082,17900610,TMIN,150,,,E, +ITE00100554,17900610,TMAX,241,,,E, +ITE00100554,17900610,TMIN,188,,,E, +GM000010962,17900610,PRCP,0,,,E, +EZE00100082,17900611,TMAX,281,,,E, +EZE00100082,17900611,TMIN,182,,,E, +ITE00100554,17900611,TMAX,213,,,E, +ITE00100554,17900611,TMIN,169,,,E, +GM000010962,17900611,PRCP,0,,,E, +EZE00100082,17900612,TMAX,260,,,E, +EZE00100082,17900612,TMIN,164,,,E, +ITE00100554,17900612,TMAX,238,,,E, +ITE00100554,17900612,TMIN,188,,,E, +GM000010962,17900612,PRCP,75,,,E, +EZE00100082,17900613,TMAX,186,,,E, +EZE00100082,17900613,TMIN,135,,,E, +ITE00100554,17900613,TMAX,265,,,E, +ITE00100554,17900613,TMIN,194,,,E, +GM000010962,17900613,PRCP,20,,,E, +EZE00100082,17900614,TMAX,167,,,E, +EZE00100082,17900614,TMIN,98,,,E, +ITE00100554,17900614,TMAX,254,,,E, +ITE00100554,17900614,TMIN,190,,,E, +GM000010962,17900614,PRCP,3,,,E, +EZE00100082,17900615,TMAX,202,,,E, +EZE00100082,17900615,TMIN,97,,,E, +ITE00100554,17900615,TMAX,256,,,E, +ITE00100554,17900615,TMIN,203,,,E, +GM000010962,17900615,PRCP,0,,,E, +EZE00100082,17900616,TMAX,220,,,E, +EZE00100082,17900616,TMIN,137,,,E, +ITE00100554,17900616,TMAX,250,,,E, +ITE00100554,17900616,TMIN,200,,,E, +GM000010962,17900616,PRCP,0,,,E, +EZE00100082,17900617,TMAX,243,,,E, +EZE00100082,17900617,TMIN,150,,,E, +ITE00100554,17900617,TMAX,263,,,E, +ITE00100554,17900617,TMIN,190,,,E, +GM000010962,17900617,PRCP,0,,,E, +EZE00100082,17900618,TMAX,253,,,E, +EZE00100082,17900618,TMIN,139,,,E, +ITE00100554,17900618,TMAX,275,,,E, +ITE00100554,17900618,TMIN,203,,,E, +GM000010962,17900618,PRCP,19,,,E, +EZE00100082,17900619,TMAX,226,,,E, +EZE00100082,17900619,TMIN,170,,,E, +ITE00100554,17900619,TMAX,181,,I,E, +ITE00100554,17900619,TMIN,181,,,E, +GM000010962,17900619,PRCP,79,,,E, +EZE00100082,17900620,TMAX,263,,,E, +EZE00100082,17900620,TMIN,151,,,E, +ITE00100554,17900620,TMAX,281,,,E, +ITE00100554,17900620,TMIN,200,,,E, +GM000010962,17900620,PRCP,0,,,E, +EZE00100082,17900621,TMAX,270,,,E, +EZE00100082,17900621,TMIN,188,,,E, +ITE00100554,17900621,TMAX,298,,,E, +ITE00100554,17900621,TMIN,204,,,E, +GM000010962,17900621,PRCP,0,,,E, +EZE00100082,17900622,TMAX,303,,,E, +EZE00100082,17900622,TMIN,157,,,E, +ITE00100554,17900622,TMAX,315,,,E, +ITE00100554,17900622,TMIN,228,,,E, +GM000010962,17900622,PRCP,0,,,E, +EZE00100082,17900623,TMAX,322,,,E, +EZE00100082,17900623,TMIN,190,,,E, +ITE00100554,17900623,TMAX,313,,,E, +ITE00100554,17900623,TMIN,231,,,E, +GM000010962,17900623,PRCP,0,,,E, +EZE00100082,17900624,TMAX,288,,,E, +EZE00100082,17900624,TMIN,220,,,E, +ITE00100554,17900624,TMAX,310,,,E, +ITE00100554,17900624,TMIN,219,,,E, +GM000010962,17900624,PRCP,29,,,E, +EZE00100082,17900625,TMAX,289,,,E, +EZE00100082,17900625,TMIN,193,,,E, +ITE00100554,17900625,TMAX,300,,,E, +ITE00100554,17900625,TMIN,228,,,E, +GM000010962,17900625,PRCP,5,,,E, +EZE00100082,17900626,TMAX,210,,,E, +EZE00100082,17900626,TMIN,130,,,E, +ITE00100554,17900626,TMAX,238,,,E, +ITE00100554,17900626,TMIN,225,,,E, +GM000010962,17900626,PRCP,154,,,E, +EZE00100082,17900627,TMAX,190,,,E, +EZE00100082,17900627,TMIN,127,,,E, +ITE00100554,17900627,TMAX,254,,,E, +ITE00100554,17900627,TMIN,154,,,E, +GM000010962,17900627,PRCP,30,,,E, +EZE00100082,17900628,TMAX,164,,,E, +EZE00100082,17900628,TMIN,126,,,E, +ITE00100554,17900628,TMAX,231,,,E, +ITE00100554,17900628,TMIN,166,,,E, +GM000010962,17900628,PRCP,58,,,E, +EZE00100082,17900629,TMAX,185,,,E, +EZE00100082,17900629,TMIN,125,,,E, +ITE00100554,17900629,TMAX,250,,,E, +ITE00100554,17900629,TMIN,178,,,E, +GM000010962,17900629,PRCP,12,,,E, +EZE00100082,17900630,TMAX,210,,,E, +EZE00100082,17900630,TMIN,135,,,E, +ITE00100554,17900630,TMAX,263,,,E, +ITE00100554,17900630,TMIN,181,,,E, +GM000010962,17900630,PRCP,11,,,E, +EZE00100082,17900701,TMAX,248,,,E, +EZE00100082,17900701,TMIN,165,,,E, +ITE00100554,17900701,TMAX,278,,,E, +ITE00100554,17900701,TMIN,203,,,E, +GM000010962,17900701,PRCP,53,,,E, +EZE00100082,17900702,TMAX,233,,,E, +EZE00100082,17900702,TMIN,178,,,E, +ITE00100554,17900702,TMAX,288,,,E, +ITE00100554,17900702,TMIN,208,,,E, +GM000010962,17900702,PRCP,31,,,E, +EZE00100082,17900703,TMAX,211,,,E, +EZE00100082,17900703,TMIN,146,,,E, +ITE00100554,17900703,TMAX,291,,,E, +ITE00100554,17900703,TMIN,213,,,E, +GM000010962,17900703,PRCP,29,,,E, +EZE00100082,17900704,TMAX,191,,,E, +EZE00100082,17900704,TMIN,150,,,E, +ITE00100554,17900704,TMAX,258,,,E, +ITE00100554,17900704,TMIN,225,,,E, +GM000010962,17900704,PRCP,12,,,E, +EZE00100082,17900705,TMAX,242,,,E, +EZE00100082,17900705,TMIN,138,,,E, +ITE00100554,17900705,TMAX,278,,,E, +ITE00100554,17900705,TMIN,203,,,E, +GM000010962,17900705,PRCP,3,,,E, +EZE00100082,17900706,TMAX,190,,,E, +EZE00100082,17900706,TMIN,140,,,E, +ITE00100554,17900706,TMAX,254,,,E, +ITE00100554,17900706,TMIN,200,,,E, +GM000010962,17900706,PRCP,90,,,E, +EZE00100082,17900707,TMAX,201,,,E, +EZE00100082,17900707,TMIN,129,,,E, +ITE00100554,17900707,TMAX,238,,,E, +ITE00100554,17900707,TMIN,158,,,E, +GM000010962,17900707,PRCP,12,,,E, +EZE00100082,17900708,TMAX,204,,,E, +EZE00100082,17900708,TMIN,129,,,E, +ITE00100554,17900708,TMAX,244,,,E, +ITE00100554,17900708,TMIN,169,,,E, +GM000010962,17900708,PRCP,53,,,E, +EZE00100082,17900709,TMAX,208,,,E, +EZE00100082,17900709,TMIN,126,,,E, +ITE00100554,17900709,TMAX,244,,,E, +ITE00100554,17900709,TMIN,191,,,E, +GM000010962,17900709,PRCP,6,,,E, +EZE00100082,17900710,TMAX,221,,,E, +EZE00100082,17900710,TMIN,150,,,E, +ITE00100554,17900710,TMAX,254,,,E, +ITE00100554,17900710,TMIN,181,,,E, +GM000010962,17900710,PRCP,0,,,E, +EZE00100082,17900711,TMAX,230,,,E, +EZE00100082,17900711,TMIN,144,,,E, +ITE00100554,17900711,TMAX,225,,,E, +ITE00100554,17900711,TMIN,200,,,E, +GM000010962,17900711,PRCP,15,,,E, +EZE00100082,17900712,TMAX,190,,,E, +EZE00100082,17900712,TMIN,142,,,E, +ITE00100554,17900712,TMAX,231,,,E, +ITE00100554,17900712,TMIN,158,,,E, +GM000010962,17900712,PRCP,129,,,E, +EZE00100082,17900713,TMAX,182,,,E, +EZE00100082,17900713,TMIN,134,,,E, +ITE00100554,17900713,TMAX,231,,,E, +ITE00100554,17900713,TMIN,163,,,E, +GM000010962,17900713,PRCP,31,,,E, +EZE00100082,17900714,TMAX,194,,,E, +EZE00100082,17900714,TMIN,131,,,E, +ITE00100554,17900714,TMAX,229,,,E, +ITE00100554,17900714,TMIN,175,,,E, +GM000010962,17900714,PRCP,9,,,E, +EZE00100082,17900715,TMAX,200,,,E, +EZE00100082,17900715,TMIN,124,,,E, +ITE00100554,17900715,TMAX,244,,,E, +ITE00100554,17900715,TMIN,179,,,E, +GM000010962,17900715,PRCP,4,,,E, +EZE00100082,17900716,TMAX,187,,,E, +EZE00100082,17900716,TMIN,126,,,E, +ITE00100554,17900716,TMAX,250,,,E, +ITE00100554,17900716,TMIN,156,,,E, +GM000010962,17900716,PRCP,25,,,E, +EZE00100082,17900717,TMAX,192,,,E, +EZE00100082,17900717,TMIN,131,,,E, +ITE00100554,17900717,TMAX,253,,,E, +ITE00100554,17900717,TMIN,175,,,E, +GM000010962,17900717,PRCP,57,,,E, +EZE00100082,17900718,TMAX,206,,,E, +EZE00100082,17900718,TMIN,139,,,E, +ITE00100554,17900718,TMAX,256,,,E, +ITE00100554,17900718,TMIN,188,,,E, +GM000010962,17900718,PRCP,42,,,E, +EZE00100082,17900719,TMAX,256,,,E, +EZE00100082,17900719,TMIN,158,,,E, +ITE00100554,17900719,TMAX,269,,,E, +ITE00100554,17900719,TMIN,194,,,E, +GM000010962,17900719,PRCP,2,,,E, +EZE00100082,17900720,TMAX,258,,,E, +EZE00100082,17900720,TMIN,164,,,E, +ITE00100554,17900720,TMAX,288,,,E, +ITE00100554,17900720,TMIN,206,,,E, +GM000010962,17900720,PRCP,42,,,E, +EZE00100082,17900721,TMAX,265,,,E, +EZE00100082,17900721,TMIN,165,,,E, +ITE00100554,17900721,TMAX,279,,,E, +ITE00100554,17900721,TMIN,203,,,E, +GM000010962,17900721,PRCP,0,,,E, +EZE00100082,17900722,TMAX,218,,,E, +EZE00100082,17900722,TMIN,145,,,E, +ITE00100554,17900722,TMAX,281,,,E, +ITE00100554,17900722,TMIN,203,,,E, +GM000010962,17900722,PRCP,35,,,E, +EZE00100082,17900723,TMAX,233,,,E, +EZE00100082,17900723,TMIN,141,,,E, +ITE00100554,17900723,TMAX,281,,,E, +ITE00100554,17900723,TMIN,228,,,E, +GM000010962,17900723,PRCP,0,,,E, +EZE00100082,17900724,TMAX,264,,,E, +EZE00100082,17900724,TMIN,134,,,E, +ITE00100554,17900724,TMAX,250,,,E, +ITE00100554,17900724,TMIN,194,,,E, +GM000010962,17900724,PRCP,0,,,E, +EZE00100082,17900725,TMAX,253,,,E, +EZE00100082,17900725,TMIN,166,,,E, +ITE00100554,17900725,TMAX,288,,,E, +ITE00100554,17900725,TMIN,200,,,E, +GM000010962,17900725,PRCP,72,,,E, +EZE00100082,17900726,TMAX,240,,,E, +EZE00100082,17900726,TMIN,155,,,E, +ITE00100554,17900726,TMAX,288,,,E, +ITE00100554,17900726,TMIN,206,,,E, +GM000010962,17900726,PRCP,62,,,E, +EZE00100082,17900727,TMAX,283,,,E, +EZE00100082,17900727,TMIN,149,,,E, +ITE00100554,17900727,TMAX,281,,,E, +ITE00100554,17900727,TMIN,213,,,E, +GM000010962,17900727,PRCP,0,,,E, +EZE00100082,17900728,TMAX,311,,,E, +EZE00100082,17900728,TMIN,174,,,E, +ITE00100554,17900728,TMAX,294,,,E, +ITE00100554,17900728,TMIN,206,,,E, +GM000010962,17900728,PRCP,0,,,E, +EZE00100082,17900729,TMAX,295,,,E, +EZE00100082,17900729,TMIN,185,,,E, +ITE00100554,17900729,TMAX,296,,,E, +ITE00100554,17900729,TMIN,225,,,E, +GM000010962,17900729,PRCP,0,,,E, +EZE00100082,17900730,TMAX,281,,,E, +EZE00100082,17900730,TMIN,171,,,E, +ITE00100554,17900730,TMAX,250,,,E, +ITE00100554,17900730,TMIN,225,,,E, +GM000010962,17900730,PRCP,14,,,E, +EZE00100082,17900731,TMAX,208,,,E, +EZE00100082,17900731,TMIN,160,,,E, +ITE00100554,17900731,TMAX,275,,,E, +ITE00100554,17900731,TMIN,200,,,E, +GM000010962,17900731,PRCP,26,,,E, +EZE00100082,17900801,TMAX,251,,,E, +EZE00100082,17900801,TMIN,148,,,E, +ITE00100554,17900801,TMAX,263,,,E, +ITE00100554,17900801,TMIN,194,,,E, +GM000010962,17900801,PRCP,30,,,E, +EZE00100082,17900802,TMAX,200,,,E, +EZE00100082,17900802,TMIN,146,,,E, +ITE00100554,17900802,TMAX,269,,,E, +ITE00100554,17900802,TMIN,190,,,E, +GM000010962,17900802,PRCP,73,,,E, +EZE00100082,17900803,TMAX,232,,,E, +EZE00100082,17900803,TMIN,152,,,E, +ITE00100554,17900803,TMAX,269,,,E, +ITE00100554,17900803,TMIN,200,,,E, +GM000010962,17900803,PRCP,0,,,E, +EZE00100082,17900804,TMAX,240,,,E, +EZE00100082,17900804,TMIN,161,,,E, +ITE00100554,17900804,TMAX,269,,,E, +ITE00100554,17900804,TMIN,203,,,E, +GM000010962,17900804,PRCP,19,,,E, +EZE00100082,17900805,TMAX,221,,,E, +EZE00100082,17900805,TMIN,154,,,E, +ITE00100554,17900805,TMAX,269,,,E, +ITE00100554,17900805,TMIN,213,,,E, +GM000010962,17900805,PRCP,0,,,E, +EZE00100082,17900806,TMAX,252,,,E, +EZE00100082,17900806,TMIN,148,,,E, +ITE00100554,17900806,TMAX,294,,,E, +ITE00100554,17900806,TMIN,213,,,E, +GM000010962,17900806,PRCP,0,,,E, +EZE00100082,17900807,TMAX,243,,,E, +EZE00100082,17900807,TMIN,179,,,E, +ITE00100554,17900807,TMAX,306,,,E, +ITE00100554,17900807,TMIN,219,,,E, +GM000010962,17900807,PRCP,0,,,E, +EZE00100082,17900808,TMAX,256,,,E, +EZE00100082,17900808,TMIN,174,,,E, +ITE00100554,17900808,TMAX,304,,,E, +ITE00100554,17900808,TMIN,225,,,E, +GM000010962,17900808,PRCP,0,,,E, +EZE00100082,17900809,TMAX,253,,,E, +EZE00100082,17900809,TMIN,166,,,E, +ITE00100554,17900809,TMAX,313,,,E, +ITE00100554,17900809,TMIN,228,,,E, +GM000010962,17900809,PRCP,7,,,E, +EZE00100082,17900810,TMAX,243,,,E, +EZE00100082,17900810,TMIN,165,,,E, +ITE00100554,17900810,TMAX,319,,,E, +ITE00100554,17900810,TMIN,238,,,E, +GM000010962,17900810,PRCP,0,,,E, +EZE00100082,17900811,TMAX,216,,,E, +EZE00100082,17900811,TMIN,165,,,E, +ITE00100554,17900811,TMAX,303,,,E, +ITE00100554,17900811,TMIN,244,,,E, +GM000010962,17900811,PRCP,0,,,E, +EZE00100082,17900812,TMAX,227,,,E, +EZE00100082,17900812,TMIN,168,,,E, +ITE00100554,17900812,TMAX,304,,,E, +ITE00100554,17900812,TMIN,238,,,E, +GM000010962,17900812,PRCP,0,,,E, +EZE00100082,17900813,TMAX,220,,,E, +EZE00100082,17900813,TMIN,162,,,E, +ITE00100554,17900813,TMAX,296,,,E, +ITE00100554,17900813,TMIN,244,,,E, +GM000010962,17900813,PRCP,0,,,E, +EZE00100082,17900814,TMAX,225,,,E, +EZE00100082,17900814,TMIN,151,,,E, +ITE00100554,17900814,TMAX,281,,,E, +ITE00100554,17900814,TMIN,219,,,E, +GM000010962,17900814,PRCP,17,,,E, +EZE00100082,17900815,TMAX,210,,,E, +EZE00100082,17900815,TMIN,147,,,E, +ITE00100554,17900815,TMAX,281,,,E, +ITE00100554,17900815,TMIN,219,,,E, +GM000010962,17900815,PRCP,39,,,E, +EZE00100082,17900816,TMAX,243,,,E, +EZE00100082,17900816,TMIN,145,,,E, +ITE00100554,17900816,TMAX,275,,,E, +ITE00100554,17900816,TMIN,225,,,E, +GM000010962,17900816,PRCP,0,,,E, +EZE00100082,17900817,TMAX,255,,,E, +EZE00100082,17900817,TMIN,180,,,E, +ITE00100554,17900817,TMAX,294,,,E, +ITE00100554,17900817,TMIN,204,,,E, +GM000010962,17900817,PRCP,5,,,E, +EZE00100082,17900818,TMAX,231,,,E, +EZE00100082,17900818,TMIN,165,,,E, +ITE00100554,17900818,TMAX,206,,,E, +ITE00100554,17900818,TMIN,206,,,E, +GM000010962,17900818,PRCP,204,,,E, +EZE00100082,17900819,TMAX,207,,,E, +EZE00100082,17900819,TMIN,158,,,E, +ITE00100554,17900819,TMAX,256,,,E, +ITE00100554,17900819,TMIN,191,,,E, +GM000010962,17900819,PRCP,22,,,E, +EZE00100082,17900820,TMAX,205,,,E, +EZE00100082,17900820,TMIN,158,,,E, +ITE00100554,17900820,TMAX,269,,,E, +ITE00100554,17900820,TMIN,193,,,E, +GM000010962,17900820,PRCP,2,,,E, +EZE00100082,17900821,TMAX,232,,,E, +EZE00100082,17900821,TMIN,144,,,E, +ITE00100554,17900821,TMAX,281,,,E, +ITE00100554,17900821,TMIN,200,,,E, +GM000010962,17900821,PRCP,0,,,E, +EZE00100082,17900822,TMAX,207,,,E, +EZE00100082,17900822,TMIN,149,,,E, +ITE00100554,17900822,TMAX,241,,,E, +ITE00100554,17900822,TMIN,213,,,E, +GM000010962,17900822,PRCP,37,,,E, +EZE00100082,17900823,TMAX,185,,,E, +EZE00100082,17900823,TMIN,131,,,E, +ITE00100554,17900823,TMAX,260,,,E, +ITE00100554,17900823,TMIN,200,,,E, +GM000010962,17900823,PRCP,19,,,E, +EZE00100082,17900824,TMAX,223,,,E, +EZE00100082,17900824,TMIN,170,,,E, +ITE00100554,17900824,TMAX,265,,,E, +ITE00100554,17900824,TMIN,194,,,E, +GM000010962,17900824,PRCP,0,,,E, +EZE00100082,17900825,TMAX,202,,,E, +EZE00100082,17900825,TMIN,150,,,E, +ITE00100554,17900825,TMAX,283,,,E, +ITE00100554,17900825,TMIN,206,,,E, +GM000010962,17900825,PRCP,0,,,E, +EZE00100082,17900826,TMAX,276,,,E, +EZE00100082,17900826,TMIN,160,,,E, +ITE00100554,17900826,TMAX,281,,,E, +ITE00100554,17900826,TMIN,203,,,E, +GM000010962,17900826,PRCP,0,,,E, +EZE00100082,17900827,TMAX,282,,,E, +EZE00100082,17900827,TMIN,198,,,E, +ITE00100554,17900827,TMAX,281,,,E, +ITE00100554,17900827,TMIN,209,,,E, +GM000010962,17900827,PRCP,22,,,E, +EZE00100082,17900828,TMAX,215,,,E, +EZE00100082,17900828,TMIN,160,,,E, +ITE00100554,17900828,TMAX,271,,,E, +ITE00100554,17900828,TMIN,206,,,E, +GM000010962,17900828,PRCP,21,,,E, +EZE00100082,17900829,TMAX,192,,,E, +EZE00100082,17900829,TMIN,145,,,E, +ITE00100554,17900829,TMAX,265,,,E, +ITE00100554,17900829,TMIN,203,,,E, +GM000010962,17900829,PRCP,7,,,E, +EZE00100082,17900830,TMAX,187,,,E, +EZE00100082,17900830,TMIN,130,,,E, +ITE00100554,17900830,TMAX,231,,,E, +ITE00100554,17900830,TMIN,194,,,E, +GM000010962,17900830,PRCP,0,,,E, +EZE00100082,17900831,TMAX,190,,,E, +EZE00100082,17900831,TMIN,137,,,E, +ITE00100554,17900831,TMAX,238,,,E, +ITE00100554,17900831,TMIN,181,,,E, +GM000010962,17900831,PRCP,0,,,E, +EZE00100082,17900901,TMAX,208,,,E, +EZE00100082,17900901,TMIN,163,,,E, +ITE00100554,17900901,TMAX,256,,,E, +ITE00100554,17900901,TMIN,188,,,E, +GM000010962,17900901,PRCP,0,,,E, +EZE00100082,17900902,TMAX,208,,,E, +EZE00100082,17900902,TMIN,151,,,E, +ITE00100554,17900902,TMAX,259,,,E, +ITE00100554,17900902,TMIN,190,,,E, +GM000010962,17900902,PRCP,2,,,E, +EZE00100082,17900903,TMAX,182,,,E, +EZE00100082,17900903,TMIN,130,,,E, +ITE00100554,17900903,TMAX,265,,,E, +ITE00100554,17900903,TMIN,196,,,E, +GM000010962,17900903,PRCP,43,,,E, +EZE00100082,17900904,TMAX,180,,,E, +EZE00100082,17900904,TMIN,121,,,E, +ITE00100554,17900904,TMAX,240,,,E, +ITE00100554,17900904,TMIN,169,,,E, +GM000010962,17900904,PRCP,11,,,E, +EZE00100082,17900905,TMAX,161,,,E, +EZE00100082,17900905,TMIN,105,,,E, +ITE00100554,17900905,TMAX,213,,,E, +ITE00100554,17900905,TMIN,153,,,E, +GM000010962,17900905,PRCP,0,,,E, +EZE00100082,17900906,TMAX,173,,,E, +EZE00100082,17900906,TMIN,100,,,E, +ITE00100554,17900906,TMAX,225,,,E, +ITE00100554,17900906,TMIN,156,,,E, +GM000010962,17900906,PRCP,10,,,E, +EZE00100082,17900907,TMAX,181,,,E, +EZE00100082,17900907,TMIN,103,,,E, +ITE00100554,17900907,TMAX,190,,,E, +ITE00100554,17900907,TMIN,171,,,E, +GM000010962,17900907,PRCP,9,,,E, +EZE00100082,17900908,TMAX,155,,,E, +EZE00100082,17900908,TMIN,126,,,E, +ITE00100554,17900908,TMAX,206,,,E, +ITE00100554,17900908,TMIN,173,,I,E, +GM000010962,17900908,PRCP,28,,,E, +EZE00100082,17900909,TMAX,146,,,E, +EZE00100082,17900909,TMIN,121,,,E, +ITE00100554,17900909,TMAX,159,,I,E, +ITE00100554,17900909,TMIN,156,,,E, +GM000010962,17900909,PRCP,7,,,E, +EZE00100082,17900910,TMAX,165,,,E, +EZE00100082,17900910,TMIN,117,,,E, +ITE00100554,17900910,TMAX,200,,,E, +ITE00100554,17900910,TMIN,106,,,E, +GM000010962,17900910,PRCP,14,,,E, +EZE00100082,17900911,TMAX,143,,,E, +EZE00100082,17900911,TMIN,117,,,E, +ITE00100554,17900911,TMAX,213,,,E, +ITE00100554,17900911,TMIN,138,,,E, +GM000010962,17900911,PRCP,31,,,E, +EZE00100082,17900912,TMAX,143,,,E, +EZE00100082,17900912,TMIN,115,,,E, +ITE00100554,17900912,TMAX,213,,,E, +ITE00100554,17900912,TMIN,150,,,E, +GM000010962,17900912,PRCP,41,,,E, +EZE00100082,17900913,TMAX,218,,,E, +EZE00100082,17900913,TMIN,134,,,E, +ITE00100554,17900913,TMAX,225,,,E, +ITE00100554,17900913,TMIN,146,,,E, +GM000010962,17900913,PRCP,0,,,E, +EZE00100082,17900914,TMAX,222,,,E, +EZE00100082,17900914,TMIN,132,,,E, +ITE00100554,17900914,TMAX,238,,,E, +ITE00100554,17900914,TMIN,153,,,E, +GM000010962,17900914,PRCP,0,,,E, +EZE00100082,17900915,TMAX,223,,,E, +EZE00100082,17900915,TMIN,145,,,E, +ITE00100554,17900915,TMAX,253,,,E, +ITE00100554,17900915,TMIN,156,,,E, +GM000010962,17900915,PRCP,0,,,E, +EZE00100082,17900916,TMAX,244,,,E, +EZE00100082,17900916,TMIN,152,,,E, +ITE00100554,17900916,TMAX,256,,,E, +ITE00100554,17900916,TMIN,150,,,E, +GM000010962,17900916,PRCP,0,,,E, +EZE00100082,17900917,TMAX,172,,,E, +EZE00100082,17900917,TMIN,116,,,E, +ITE00100554,17900917,TMAX,253,,,E, +ITE00100554,17900917,TMIN,163,,,E, +GM000010962,17900917,PRCP,230,,,E, +EZE00100082,17900918,TMAX,199,,,E, +EZE00100082,17900918,TMIN,90,,,E, +ITE00100554,17900918,TMAX,250,,,E, +ITE00100554,17900918,TMIN,175,,,E, +GM000010962,17900918,PRCP,0,,,E, +EZE00100082,17900919,TMAX,216,,,E, +EZE00100082,17900919,TMIN,100,,,E, +ITE00100554,17900919,TMAX,260,,,E, +ITE00100554,17900919,TMIN,181,,,E, +GM000010962,17900919,PRCP,0,,,E, +EZE00100082,17900920,TMAX,232,,,E, +EZE00100082,17900920,TMIN,128,,,E, +ITE00100554,17900920,TMAX,256,,,E, +ITE00100554,17900920,TMIN,200,,,E, +GM000010962,17900920,PRCP,0,,,E, +EZE00100082,17900921,TMAX,200,,,E, +EZE00100082,17900921,TMIN,118,,,E, +ITE00100554,17900921,TMAX,219,,,E, +ITE00100554,17900921,TMIN,196,,,E, +GM000010962,17900921,PRCP,103,,,E, +EZE00100082,17900922,TMAX,142,,,E, +EZE00100082,17900922,TMIN,112,,,E, +ITE00100554,17900922,TMAX,215,,,E, +ITE00100554,17900922,TMIN,190,,,E, +GM000010962,17900922,PRCP,42,,,E, +EZE00100082,17900923,TMAX,158,,,E, +EZE00100082,17900923,TMIN,98,,,E, +ITE00100554,17900923,TMAX,206,,,E, +ITE00100554,17900923,TMIN,181,,,E, +GM000010962,17900923,PRCP,0,,,E, +EZE00100082,17900924,TMAX,166,,,E, +EZE00100082,17900924,TMIN,114,,,E, +ITE00100554,17900924,TMAX,206,,,E, +ITE00100554,17900924,TMIN,178,,,E, +GM000010962,17900924,PRCP,13,,,E, +EZE00100082,17900925,TMAX,153,,,E, +EZE00100082,17900925,TMIN,118,,,E, +ITE00100554,17900925,TMAX,225,,,E, +ITE00100554,17900925,TMIN,159,,,E, +GM000010962,17900925,PRCP,123,,,E, +EZE00100082,17900926,TMAX,128,,,E, +EZE00100082,17900926,TMIN,85,,,E, +ITE00100554,17900926,TMAX,215,,,E, +ITE00100554,17900926,TMIN,156,,,E, +GM000010962,17900926,PRCP,18,,,E, +EZE00100082,17900927,TMAX,115,,,E, +EZE00100082,17900927,TMIN,62,,,E, +ITE00100554,17900927,TMAX,213,,,E, +ITE00100554,17900927,TMIN,150,,,E, +GM000010962,17900927,PRCP,31,,,E, +EZE00100082,17900928,TMAX,133,,,E, +EZE00100082,17900928,TMIN,43,,,E, +ITE00100554,17900928,TMAX,200,,,E, +ITE00100554,17900928,TMIN,153,,,E, +GM000010962,17900928,PRCP,0,,,E, +EZE00100082,17900929,TMAX,137,,,E, +EZE00100082,17900929,TMIN,52,,,E, +ITE00100554,17900929,TMAX,200,,,E, +ITE00100554,17900929,TMIN,138,,,E, +GM000010962,17900929,PRCP,0,,,E, +EZE00100082,17900930,TMAX,140,,,E, +EZE00100082,17900930,TMIN,89,,,E, +ITE00100554,17900930,TMAX,206,,,E, +ITE00100554,17900930,TMIN,146,,,E, +GM000010962,17900930,PRCP,11,,,E, +EZE00100082,17901001,TMAX,133,,,E, +EZE00100082,17901001,TMIN,96,,,E, +ITE00100554,17901001,TMAX,188,,,E, +ITE00100554,17901001,TMIN,150,,,E, +GM000010962,17901001,PRCP,4,,,E, +EZE00100082,17901002,TMAX,130,,,E, +EZE00100082,17901002,TMIN,93,,,E, +ITE00100554,17901002,TMAX,190,,,E, +ITE00100554,17901002,TMIN,153,,,E, +GM000010962,17901002,PRCP,0,,,E, +EZE00100082,17901003,TMAX,150,,,E, +EZE00100082,17901003,TMIN,74,,,E, +ITE00100554,17901003,TMAX,188,,,E, +ITE00100554,17901003,TMIN,150,,,E, +GM000010962,17901003,PRCP,0,,,E, +EZE00100082,17901004,TMAX,150,,,E, +EZE00100082,17901004,TMIN,71,,,E, +ITE00100554,17901004,TMAX,209,,,E, +ITE00100554,17901004,TMIN,153,,,E, +GM000010962,17901004,PRCP,0,,,E, +EZE00100082,17901005,TMAX,160,,,E, +EZE00100082,17901005,TMIN,60,,,E, +ITE00100554,17901005,TMAX,215,,,E, +ITE00100554,17901005,TMIN,150,,,E, +GM000010962,17901005,PRCP,0,,,E, +EZE00100082,17901006,TMAX,179,,,E, +EZE00100082,17901006,TMIN,85,,,E, +ITE00100554,17901006,TMAX,219,,,E, +ITE00100554,17901006,TMIN,150,,,E, +GM000010962,17901006,PRCP,0,,,E, +EZE00100082,17901007,TMAX,160,,,E, +EZE00100082,17901007,TMIN,87,,,E, +ITE00100554,17901007,TMAX,213,,,E, +ITE00100554,17901007,TMIN,153,,,E, +GM000010962,17901007,PRCP,0,,,E, +EZE00100082,17901008,TMAX,163,,,E, +EZE00100082,17901008,TMIN,95,,,E, +ITE00100554,17901008,TMAX,215,,,E, +ITE00100554,17901008,TMIN,159,,,E, +GM000010962,17901008,PRCP,0,,,E, +EZE00100082,17901009,TMAX,189,,,E, +EZE00100082,17901009,TMIN,129,,,E, +ITE00100554,17901009,TMAX,183,,,E, +ITE00100554,17901009,TMIN,158,,,E, +GM000010962,17901009,PRCP,3,,,E, +EZE00100082,17901010,TMAX,129,,,E, +EZE00100082,17901010,TMIN,78,,,E, +ITE00100554,17901010,TMAX,184,,,E, +ITE00100554,17901010,TMIN,156,,,E, +GM000010962,17901010,PRCP,183,,,E, +EZE00100082,17901011,TMAX,100,,,E, +EZE00100082,17901011,TMIN,65,,,E, +ITE00100554,17901011,TMAX,184,,,E, +ITE00100554,17901011,TMIN,146,,,E, +GM000010962,17901011,PRCP,2,,,E, +EZE00100082,17901012,TMAX,120,,,E, +EZE00100082,17901012,TMIN,58,,,E, +ITE00100554,17901012,TMAX,181,,,E, +ITE00100554,17901012,TMIN,140,,,E, +GM000010962,17901012,PRCP,2,,,E, +EZE00100082,17901013,TMAX,102,,,E, +EZE00100082,17901013,TMIN,50,,,E, +ITE00100554,17901013,TMAX,181,,,E, +ITE00100554,17901013,TMIN,115,,,E, +GM000010962,17901013,PRCP,4,,,E, +EZE00100082,17901014,TMAX,114,,,E, +EZE00100082,17901014,TMIN,73,,,E, +ITE00100554,17901014,TMAX,184,,,E, +ITE00100554,17901014,TMIN,115,,,E, +GM000010962,17901014,PRCP,26,,,E, +EZE00100082,17901015,TMAX,158,,,E, +EZE00100082,17901015,TMIN,100,,,E, +ITE00100554,17901015,TMAX,188,,,E, +ITE00100554,17901015,TMIN,119,,,E, +GM000010962,17901015,PRCP,0,,,E, +EZE00100082,17901016,TMAX,136,,,E, +EZE00100082,17901016,TMIN,75,,,E, +ITE00100554,17901016,TMAX,190,,,E, +ITE00100554,17901016,TMIN,119,,,E, +GM000010962,17901016,PRCP,0,,,E, +EZE00100082,17901017,TMAX,109,,,E, +EZE00100082,17901017,TMIN,60,,,E, +ITE00100554,17901017,TMAX,194,,,E, +ITE00100554,17901017,TMIN,135,,,E, +GM000010962,17901017,PRCP,0,,,E, +EZE00100082,17901018,TMAX,124,,,E, +EZE00100082,17901018,TMIN,41,,,E, +ITE00100554,17901018,TMAX,196,,,E, +ITE00100554,17901018,TMIN,150,,,E, +GM000010962,17901018,PRCP,0,,,E, +EZE00100082,17901019,TMAX,126,,,E, +EZE00100082,17901019,TMIN,73,,,E, +ITE00100554,17901019,TMAX,206,,,E, +ITE00100554,17901019,TMIN,144,,,E, +GM000010962,17901019,PRCP,44,,,E, +EZE00100082,17901020,TMAX,99,,,E, +EZE00100082,17901020,TMIN,60,,,E, +ITE00100554,17901020,TMAX,196,,,E, +ITE00100554,17901020,TMIN,131,,,E, +GM000010962,17901020,PRCP,22,,,E, +EZE00100082,17901021,TMAX,78,,,E, +EZE00100082,17901021,TMIN,29,,,E, +ITE00100554,17901021,TMAX,194,,,E, +ITE00100554,17901021,TMIN,140,,,E, +GM000010962,17901021,PRCP,0,,,E, +EZE00100082,17901022,TMAX,72,,,E, +EZE00100082,17901022,TMIN,11,,,E, +ITE00100554,17901022,TMAX,175,,,E, +ITE00100554,17901022,TMIN,138,,,E, +GM000010962,17901022,PRCP,0,,,E, +EZE00100082,17901023,TMAX,74,,,E, +EZE00100082,17901023,TMIN,3,,,E, +ITE00100554,17901023,TMAX,163,,,E, +ITE00100554,17901023,TMIN,131,,,E, +GM000010962,17901023,PRCP,0,,,E, +EZE00100082,17901024,TMAX,88,,,E, +EZE00100082,17901024,TMIN,0,,,E, +ITE00100554,17901024,TMAX,150,,,E, +ITE00100554,17901024,TMIN,140,,,E, +GM000010962,17901024,PRCP,9,,,E, +EZE00100082,17901025,TMAX,76,,,E, +EZE00100082,17901025,TMIN,51,,,E, +ITE00100554,17901025,TMAX,165,,,E, +ITE00100554,17901025,TMIN,144,,,E, +GM000010962,17901025,PRCP,20,,,E, +EZE00100082,17901026,TMAX,118,,,E, +EZE00100082,17901026,TMIN,57,,,E, +ITE00100554,17901026,TMAX,178,,,E, +ITE00100554,17901026,TMIN,163,,,E, +GM000010962,17901026,PRCP,8,,,E, +EZE00100082,17901027,TMAX,78,,,E, +EZE00100082,17901027,TMIN,44,,,E, +ITE00100554,17901027,TMAX,181,,,E, +ITE00100554,17901027,TMIN,158,,,E, +GM000010962,17901027,PRCP,53,,,E, +EZE00100082,17901028,TMAX,66,,,E, +EZE00100082,17901028,TMIN,45,,,E, +ITE00100554,17901028,TMAX,175,,,E, +ITE00100554,17901028,TMIN,153,,,E, +GM000010962,17901028,PRCP,35,,,E, +EZE00100082,17901029,TMAX,67,,,E, +EZE00100082,17901029,TMIN,34,,,E, +ITE00100554,17901029,TMAX,165,,,E, +ITE00100554,17901029,TMIN,153,,,E, +GM000010962,17901029,PRCP,10,,,E, +EZE00100082,17901030,TMAX,61,,,E, +EZE00100082,17901030,TMIN,27,,,E, +ITE00100554,17901030,TMAX,163,,,E, +ITE00100554,17901030,TMIN,140,,,E, +GM000010962,17901030,PRCP,27,,,E, +EZE00100082,17901031,TMAX,44,,,E, +EZE00100082,17901031,TMIN,22,,,E, +ITE00100554,17901031,TMAX,153,,,E, +ITE00100554,17901031,TMIN,125,,,E, +GM000010962,17901031,PRCP,10,,,E, +EZE00100082,17901101,TMAX,46,,,E, +EZE00100082,17901101,TMIN,23,,,E, +ITE00100554,17901101,TMAX,150,,,E, +ITE00100554,17901101,TMIN,103,,,E, +GM000010962,17901101,PRCP,18,,,E, +EZE00100082,17901102,TMAX,74,,,E, +EZE00100082,17901102,TMIN,12,,,E, +ITE00100554,17901102,TMAX,119,,,E, +ITE00100554,17901102,TMIN,100,,,E, +GM000010962,17901102,PRCP,0,,,E, +EZE00100082,17901103,TMAX,84,,,E, +EZE00100082,17901103,TMIN,48,,,E, +ITE00100554,17901103,TMAX,103,,,E, +ITE00100554,17901103,TMIN,90,,,E, +GM000010962,17901103,PRCP,15,,,E, +EZE00100082,17901104,TMAX,105,,,E, +EZE00100082,17901104,TMIN,63,,,E, +ITE00100554,17901104,TMAX,113,,,E, +ITE00100554,17901104,TMIN,78,,,E, +GM000010962,17901104,PRCP,26,,,E, +EZE00100082,17901105,TMAX,100,,,E, +EZE00100082,17901105,TMIN,71,,,E, +ITE00100554,17901105,TMAX,134,,,E, +ITE00100554,17901105,TMIN,100,,,E, +GM000010962,17901105,PRCP,39,,,E, +EZE00100082,17901106,TMAX,71,,,E, +EZE00100082,17901106,TMIN,32,,,E, +ITE00100554,17901106,TMAX,119,,,E, +ITE00100554,17901106,TMIN,59,,,E, +GM000010962,17901106,PRCP,19,,,E, +EZE00100082,17901107,TMAX,62,,,E, +EZE00100082,17901107,TMIN,16,,,E, +ITE00100554,17901107,TMAX,103,,,E, +ITE00100554,17901107,TMIN,84,,,E, +GM000010962,17901107,PRCP,2,,,E, +EZE00100082,17901108,TMAX,53,,,E, +EZE00100082,17901108,TMIN,16,,,E, +ITE00100554,17901108,TMAX,96,,,E, +ITE00100554,17901108,TMIN,75,,,E, +GM000010962,17901108,PRCP,0,,,E, +EZE00100082,17901109,TMAX,70,,,E, +EZE00100082,17901109,TMIN,26,,,E, +ITE00100554,17901109,TMAX,90,,,E, +ITE00100554,17901109,TMIN,63,,,E, +GM000010962,17901109,PRCP,0,,,E, +EZE00100082,17901110,TMAX,60,,,E, +EZE00100082,17901110,TMIN,22,,,E, +ITE00100554,17901110,TMAX,119,,,E, +ITE00100554,17901110,TMIN,96,,,E, +GM000010962,17901110,PRCP,0,,,E, +EZE00100082,17901111,TMAX,66,,,E, +EZE00100082,17901111,TMIN,50,,,E, +ITE00100554,17901111,TMAX,128,,,E, +ITE00100554,17901111,TMIN,96,,,E, +GM000010962,17901111,PRCP,0,,,E, +EZE00100082,17901112,TMAX,65,,,E, +EZE00100082,17901112,TMIN,17,,,E, +ITE00100554,17901112,TMAX,138,,,E, +ITE00100554,17901112,TMIN,106,,,E, +GM000010962,17901112,PRCP,0,,,E, +EZE00100082,17901113,TMAX,17,,,E, +EZE00100082,17901113,TMIN,5,,,E, +ITE00100554,17901113,TMAX,131,,,E, +ITE00100554,17901113,TMIN,100,,,E, +GM000010962,17901113,PRCP,0,,,E, +EZE00100082,17901114,TMAX,16,,,E, +EZE00100082,17901114,TMIN,0,,,E, +ITE00100554,17901114,TMAX,131,,,E, +ITE00100554,17901114,TMIN,100,,I,E, +GM000010962,17901114,PRCP,0,,,E, +EZE00100082,17901115,TMAX,25,,,E, +EZE00100082,17901115,TMIN,16,,,E, +ITE00100554,17901115,TMAX,84,,I,E, +ITE00100554,17901115,TMIN,69,,,E, +GM000010962,17901115,PRCP,0,,,E, +EZE00100082,17901116,TMAX,36,,,E, +EZE00100082,17901116,TMIN,-14,,,E, +ITE00100554,17901116,TMAX,75,,,E, +ITE00100554,17901116,TMIN,50,,,E, +GM000010962,17901116,PRCP,2,,,E, +EZE00100082,17901117,TMAX,21,,,E, +EZE00100082,17901117,TMIN,-30,,,E, +ITE00100554,17901117,TMAX,69,,,E, +ITE00100554,17901117,TMIN,25,,,E, +GM000010962,17901117,PRCP,2,,,E, +EZE00100082,17901118,TMAX,13,,,E, +EZE00100082,17901118,TMIN,-31,,,E, +ITE00100554,17901118,TMAX,69,,,E, +ITE00100554,17901118,TMIN,9,,,E, +GM000010962,17901118,PRCP,0,,,E, +EZE00100082,17901119,TMAX,12,,,E, +EZE00100082,17901119,TMIN,-11,,,E, +ITE00100554,17901119,TMAX,63,,,E, +ITE00100554,17901119,TMIN,35,,,E, +GM000010962,17901119,PRCP,0,,,E, +EZE00100082,17901120,TMAX,24,,,E, +EZE00100082,17901120,TMIN,6,,,E, +ITE00100554,17901120,TMAX,63,,,E, +ITE00100554,17901120,TMIN,44,,,E, +GM000010962,17901120,PRCP,0,,,E, +EZE00100082,17901121,TMAX,65,,,E, +EZE00100082,17901121,TMIN,6,,,E, +ITE00100554,17901121,TMAX,63,,,E, +ITE00100554,17901121,TMIN,54,,,E, +GM000010962,17901121,PRCP,10,,,E, +EZE00100082,17901122,TMAX,72,,,E, +EZE00100082,17901122,TMIN,36,,,E, +ITE00100554,17901122,TMAX,81,,,E, +ITE00100554,17901122,TMIN,66,,,E, +GM000010962,17901122,PRCP,0,,,E, +EZE00100082,17901123,TMAX,58,,,E, +EZE00100082,17901123,TMIN,28,,,E, +ITE00100554,17901123,TMAX,94,,,E, +ITE00100554,17901123,TMIN,81,,,E, +GM000010962,17901123,PRCP,0,,,E, +EZE00100082,17901124,TMAX,57,,,E, +EZE00100082,17901124,TMIN,31,,,E, +ITE00100554,17901124,TMAX,100,,I,E, +ITE00100554,17901124,TMIN,96,,,E, +GM000010962,17901124,PRCP,3,,,E, +EZE00100082,17901125,TMAX,75,,,E, +EZE00100082,17901125,TMIN,31,,,E, +ITE00100554,17901125,TMAX,150,,,E, +ITE00100554,17901125,TMIN,116,,I,E, +GM000010962,17901125,PRCP,2,,,E, +EZE00100082,17901126,TMAX,83,,,E, +EZE00100082,17901126,TMIN,54,,,E, +ITE00100554,17901126,TMAX,138,,,E, +ITE00100554,17901126,TMIN,113,,,E, +GM000010962,17901126,PRCP,0,,,E, +EZE00100082,17901127,TMAX,83,,,E, +EZE00100082,17901127,TMIN,42,,,E, +ITE00100554,17901127,TMAX,131,,,E, +ITE00100554,17901127,TMIN,103,,I,E, +GM000010962,17901127,PRCP,17,,,E, +EZE00100082,17901128,TMAX,42,,,E, +EZE00100082,17901128,TMIN,12,,,E, +ITE00100554,17901128,TMAX,88,,I,E, +ITE00100554,17901128,TMIN,53,,,E, +GM000010962,17901128,PRCP,16,,,E, +EZE00100082,17901129,TMAX,26,,,E, +EZE00100082,17901129,TMIN,10,,,E, +ITE00100554,17901129,TMAX,56,,,E, +ITE00100554,17901129,TMIN,44,,,E, +GM000010962,17901129,PRCP,8,,,E, +EZE00100082,17901130,TMAX,27,,,E, +EZE00100082,17901130,TMIN,-6,,,E, +ITE00100554,17901130,TMAX,38,,,E, +ITE00100554,17901130,TMIN,28,,,E, +GM000010962,17901130,PRCP,0,,,E, +EZE00100082,17901201,TMAX,25,,,E, +EZE00100082,17901201,TMIN,-16,,,E, +ITE00100554,17901201,TMAX,41,,,E, +ITE00100554,17901201,TMIN,29,,,E, +GM000010962,17901201,PRCP,0,,,E, +EZE00100082,17901202,TMAX,50,,,E, +EZE00100082,17901202,TMIN,9,,,E, +ITE00100554,17901202,TMAX,75,,,E, +ITE00100554,17901202,TMIN,50,,,E, +GM000010962,17901202,PRCP,0,,,E, +EZE00100082,17901203,TMAX,67,,,E, +EZE00100082,17901203,TMIN,40,,,E, +ITE00100554,17901203,TMAX,50,,,E, +ITE00100554,17901203,TMIN,15,,,E, +GM000010962,17901203,PRCP,4,,,E, +EZE00100082,17901204,TMAX,88,,,E, +EZE00100082,17901204,TMIN,45,,,E, +ITE00100554,17901204,TMAX,81,,,E, +ITE00100554,17901204,TMIN,31,,,E, +GM000010962,17901204,PRCP,24,,,E, +EZE00100082,17901205,TMAX,63,,,E, +EZE00100082,17901205,TMIN,20,,,E, +ITE00100554,17901205,TMAX,54,,,E, +ITE00100554,17901205,TMIN,16,,,E, +GM000010962,17901205,PRCP,7,,,E, +EZE00100082,17901206,TMAX,38,,,E, +EZE00100082,17901206,TMIN,14,,,E, +ITE00100554,17901206,TMAX,81,,,E, +ITE00100554,17901206,TMIN,38,,,E, +GM000010962,17901206,PRCP,40,,,E, +EZE00100082,17901207,TMAX,22,,,E, +EZE00100082,17901207,TMIN,3,,,E, +ITE00100554,17901207,TMAX,50,,,E, +ITE00100554,17901207,TMIN,13,,,E, +GM000010962,17901207,PRCP,30,,,E, +EZE00100082,17901208,TMAX,20,,,E, +EZE00100082,17901208,TMIN,-8,,,E, +ITE00100554,17901208,TMAX,25,,,E, +ITE00100554,17901208,TMIN,-13,,,E, +GM000010962,17901208,PRCP,0,,,E, From 637cb8644e2d7f9695c1ac760d572a9655644732 Mon Sep 17 00:00:00 2001 From: snappy-sachin Date: Wed, 27 Nov 2019 18:17:44 +0530 Subject: [PATCH 019/101] Snap 2919 : Implementation of Structured Streaming UI Tab (#1473) * Code changes for SNAP-2919 : - Adding toString method in SnappyStoreSink class --- .../org/apache/spark/sql/streaming/SnappySinkCallback.scala | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/core/src/main/scala/org/apache/spark/sql/streaming/SnappySinkCallback.scala b/core/src/main/scala/org/apache/spark/sql/streaming/SnappySinkCallback.scala index 3bf0ba161e..6e893d6137 100644 --- a/core/src/main/scala/org/apache/spark/sql/streaming/SnappySinkCallback.scala +++ b/core/src/main/scala/org/apache/spark/sql/streaming/SnappySinkCallback.scala @@ -223,6 +223,11 @@ case class SnappyStoreSink(snappySession: SnappySession, ds.queryExecution.toRdd, StructType(ds.schema.fields)) } + + override def toString: String = { + val params = parameters + ("sinkCallback" -> sinkCallback.getClass.getName) + s"SnappyStoreSink[${params.mkString(", ")}]" + } } import org.apache.spark.sql.snappy._ From 6f03fd3ac42c91fcb8aa29f3ba81b67148761df1 Mon Sep 17 00:00:00 2001 From: Sachin Kapse Date: Wed, 27 Nov 2019 18:20:08 +0530 Subject: [PATCH 020/101] Linking latest spark submodule. --- spark | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spark b/spark index c876f627e0..1cdbfb77bd 160000 --- a/spark +++ b/spark @@ -1 +1 @@ -Subproject commit c876f627e00a3d2b7770b37400059c26003658a8 +Subproject commit 1cdbfb77bde9524237e7c02250c01d1f024ed5d1 From 3d0add842485e388515b4b6a4ac2ef8fe26902c1 Mon Sep 17 00:00:00 2001 From: Neeraj Kumar Date: Wed, 27 Nov 2019 20:32:50 +0530 Subject: [PATCH 021/101] Fixed SNAP-3250. But we need to synchronize the add/drop of functions in the meta region. The current while loop is risky. --- .../main/scala/org/apache/spark/sql/internal/JarUtils.scala | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/core/src/main/scala/org/apache/spark/sql/internal/JarUtils.scala b/core/src/main/scala/org/apache/spark/sql/internal/JarUtils.scala index fbc7a3cedd..d1b3d5e23f 100644 --- a/core/src/main/scala/org/apache/spark/sql/internal/JarUtils.scala +++ b/core/src/main/scala/org/apache/spark/sql/internal/JarUtils.scala @@ -171,10 +171,11 @@ object ContextJarUtils extends Logging { do { val oldObj = r.get(k) if (oldObj != null) { - val newValue = oldObj.asInstanceOf[String].replace(item, "") + old1 = oldObj.asInstanceOf[String] + val newValue = old1.replace(item, "") old2 = r.put(k, newValue) } - } while (old1 != old2) + } while (old1 != old2.asInstanceOf[String]) } def checkItemExists(k: String, item: String): Boolean = { From 3834227d6608c064ad877ae2b84cf6c6d4362f6b Mon Sep 17 00:00:00 2001 From: Subodh Chiwate <45190931+schiwate@users.noreply.github.com> Date: Thu, 28 Nov 2019 11:48:50 +0530 Subject: [PATCH 022/101] Snap 3223 Test case for com.snappydata.jdbc.ClientDriver class (#1484) Allowing to executing a query using driver class com.snappydata.jdbc.ClientDriver. --- .../io/snappydata/CommandLineToolsSuite.scala | 24 +++++++++++++++++++ store | 2 +- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/core/src/test/scala/io/snappydata/CommandLineToolsSuite.scala b/core/src/test/scala/io/snappydata/CommandLineToolsSuite.scala index 51caf3ba06..07683f07aa 100644 --- a/core/src/test/scala/io/snappydata/CommandLineToolsSuite.scala +++ b/core/src/test/scala/io/snappydata/CommandLineToolsSuite.scala @@ -18,10 +18,13 @@ package io.snappydata import java.io._ +import java.sql.{Connection, DriverManager} import scala.language.{implicitConversions, postfixOps} import scala.sys.process._ +import org.apache.spark.sql.collection.Utils + class CommandLineToolsSuite extends SnappyTestRunner { override def servers: String = s"$localHostName\n" @@ -309,4 +312,25 @@ class CommandLineToolsSuite extends SnappyTestRunner { } } + + test ("SNAP-3223 Executing query using driver class com.snappydata.jdbc.ClientDriver"){ + // Adding test case here to reuse the infrastructure of already running cluster + // created by this suite. + def getJdbcConnectionWithComSnappyData(netPort: Int): Connection = { + val driver = "com.snappydata.jdbc.ClientDriver" + Utils.classForName(driver).newInstance + var url: String = "jdbc:snappydata://localhost:" + netPort + "/" + DriverManager.getConnection(url) + } + + val jdbcConn = getJdbcConnectionWithComSnappyData(1527) + val stmt = jdbcConn.createStatement() + assert(stmt.execute("show schemas")) + val result = stmt.getResultSet + var count = 0 + while(result.next()){ + println(result.getString(1)) + count = count + 1 + } + } } diff --git a/store b/store index 68d5ead5f6..34152ef261 160000 --- a/store +++ b/store @@ -1 +1 @@ -Subproject commit 68d5ead5f6b15c4c2e8b19ba6584b0f4a57fe85b +Subproject commit 34152ef2619c28ae345f6a152d988c2d2878804d From 1d8dcf12c9e917f0d9ccd274fa22fd0b1b8b1d1e Mon Sep 17 00:00:00 2001 From: schiwate Date: Thu, 28 Nov 2019 11:50:41 +0530 Subject: [PATCH 023/101] Linking store --- store | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/store b/store index 34152ef261..68d5ead5f6 160000 --- a/store +++ b/store @@ -1 +1 @@ -Subproject commit 34152ef2619c28ae345f6a152d988c2d2878804d +Subproject commit 68d5ead5f6b15c4c2e8b19ba6584b0f4a57fe85b From 5c5c2ce24dbeed9b6cba0d3b3c74c664355d0a73 Mon Sep 17 00:00:00 2001 From: kneeraj Date: Thu, 28 Nov 2019 17:30:42 +0530 Subject: [PATCH 024/101] Addition of an option in the exec scala to return df instead of printlns (#1488) * New option to exec scala 'returnDF' - If this hint is there then last dataset is returned as resultset which is much better for jdbc/odbc type of access. * Added multiple unit tests for 'exec scala' and snapp-scala shell --- .../QueryRoutingDUnitSecurityTest.scala | 68 +++++++- .../gemxd/ClusterCallbacksImpl.scala | 4 +- .../gemxd/SparkSQLExecuteImpl.scala | 9 +- .../RemoteInterpreterStateHolder.scala | 27 +++- .../SnappyInterpreterExecute.scala | 10 +- .../io/snappydata/CommandLineToolsSuite.scala | 150 +++++++++++++++++- .../io/snappydata/SnappyTestRunner.scala | 24 ++- .../quickstart/ExampleTestSuite.scala | 4 +- 8 files changed, 274 insertions(+), 22 deletions(-) diff --git a/cluster/src/dunit/scala/io/snappydata/cluster/QueryRoutingDUnitSecurityTest.scala b/cluster/src/dunit/scala/io/snappydata/cluster/QueryRoutingDUnitSecurityTest.scala index 04046c89a9..cfe29ec993 100644 --- a/cluster/src/dunit/scala/io/snappydata/cluster/QueryRoutingDUnitSecurityTest.scala +++ b/cluster/src/dunit/scala/io/snappydata/cluster/QueryRoutingDUnitSecurityTest.scala @@ -17,11 +17,10 @@ package io.snappydata.cluster -import java.sql.{BatchUpdateException, Connection, DriverManager, ResultSet, SQLException} +import java.sql._ import io.snappydata.cluster.ClusterManagerLDAPTestBase.thriftPort import io.snappydata.test.dunit.AvailablePortHelper - import org.apache.spark.Logging import org.apache.spark.sql.collection.Utils @@ -142,6 +141,71 @@ class QueryRoutingDUnitSecurityTest(val s: String) // scalastyle:on println QueryRoutingDUnitSecurityTest.checkMetastoreAccess(adminUser, jdbcUser4, serverHostPort) } + + private def doExecScalaSimpleStuff(st: Statement, expectException: Boolean = false): Unit = { + try { + st.execute("exec scala val x = 5") + val rs = st.getResultSet + assert(rs.next()) + assert(rs.getString(1).equals("x: Int = 5")) + if (expectException) assert(false, "expected exception") + } catch { + case sqle: SQLException => { + if (expectException) { + // SQLState should be + assert("42504".equals(sqle.getSQLState)) + } else { + sqle.printStackTrace() + println(s"sqle state: ${sqle.getSQLState}") + assert(false, "did not expect exception") + } + } + } + } + + def testExecScalaGrantRevoke(): Unit = { + val adminUser = ClusterManagerLDAPTestBase.admin + val nonAdminUser = "gemfire3" + + val serverHostPort = AvailablePortHelper.getRandomAvailableTCPPort + vm2.invoke(classOf[ClusterManagerTestBase], "startNetServer", serverHostPort) + // scalastyle:off println + val connAdmin = QueryRoutingDUnitSecurityTest.netConnection(serverHostPort, adminUser, adminUser) + val st = connAdmin.createStatement() + doExecScalaSimpleStuff(st) + val connNoAdmin = QueryRoutingDUnitSecurityTest.netConnection(serverHostPort, nonAdminUser, nonAdminUser) + val st2 = connNoAdmin.createStatement() + doExecScalaSimpleStuff(st2, true) + st.execute(s"grant privilege exec scala to $nonAdminUser") + doExecScalaSimpleStuff(st2) + st.execute(s"revoke privilege exec scala from $nonAdminUser") + doExecScalaSimpleStuff(st2, true) + try { + st2.execute(s"grant privilege exec scala to $nonAdminUser") + assert(false, "expected exception in granting as not super user") + } catch { + case sqle: SQLException => if (!"4250A".equals(sqle.getSQLState)) { + throw sqle + } + } + // allow gemGroup3 -- allowed users then will be gemfire6, 7 and 8 + // Before grant expect exception + val connNoAdminGrp1 = QueryRoutingDUnitSecurityTest.netConnection(serverHostPort, "gemfire7", "gemfire7") + val st7 = connNoAdminGrp1.createStatement() + doExecScalaSimpleStuff(st7, true) + st.execute(s"grant privilege exec scala to LDAPGROUP:gemGroup3") + doExecScalaSimpleStuff(st7) + val connNoAdminGrp2 = QueryRoutingDUnitSecurityTest.netConnection(serverHostPort, "gemfire8", "gemfire8") + val st8 = connNoAdminGrp2.createStatement() + doExecScalaSimpleStuff(st8) + // now revoke all and expect exception + st.execute(s"revoke privilege exec scala from $nonAdminUser,LDAPGROUP:gemGroup3") + doExecScalaSimpleStuff(st2, true) + doExecScalaSimpleStuff(st7, true) + doExecScalaSimpleStuff(st8, true) + // Only admin should be able to run + doExecScalaSimpleStuff(st) + } } object QueryRoutingDUnitSecurityTest { diff --git a/cluster/src/main/scala/io/snappydata/gemxd/ClusterCallbacksImpl.scala b/cluster/src/main/scala/io/snappydata/gemxd/ClusterCallbacksImpl.scala index 62192b42c6..55ec47884e 100644 --- a/cluster/src/main/scala/io/snappydata/gemxd/ClusterCallbacksImpl.scala +++ b/cluster/src/main/scala/io/snappydata/gemxd/ClusterCallbacksImpl.scala @@ -91,13 +91,13 @@ object ClusterCallbacksImpl extends ClusterCallbacks with Logging { ExecutorInitiator.stop() } - override def getSQLExecute(sql: String, schema: String, ctx: LeadNodeExecutionContext, + override def getSQLExecute(df: AnyRef, sql: String, schema: String, ctx: LeadNodeExecutionContext, v: Version, isPreparedStatement: Boolean, isPreparedPhase: Boolean, pvs: ParameterValueSet): SparkSQLExecute = { if (isPreparedStatement && isPreparedPhase) { new SparkSQLPrepareImpl(sql, schema, ctx, v) } else { - new SparkSQLExecuteImpl(sql, schema, ctx, v, Option(pvs)) + new SparkSQLExecuteImpl(df, sql, schema, ctx, v, Option(pvs)) } } diff --git a/cluster/src/main/scala/io/snappydata/gemxd/SparkSQLExecuteImpl.scala b/cluster/src/main/scala/io/snappydata/gemxd/SparkSQLExecuteImpl.scala index acc27ad02d..e09d726807 100644 --- a/cluster/src/main/scala/io/snappydata/gemxd/SparkSQLExecuteImpl.scala +++ b/cluster/src/main/scala/io/snappydata/gemxd/SparkSQLExecuteImpl.scala @@ -44,7 +44,7 @@ import org.apache.spark.sql.catalyst.expressions import org.apache.spark.sql.catalyst.util.DateTimeUtils import org.apache.spark.sql.collection.Utils import org.apache.spark.sql.types._ -import org.apache.spark.sql.{CachedDataFrame, SnappyContext, SnappySession} +import org.apache.spark.sql.{CachedDataFrame, Dataset, SnappyContext, SnappySession} import org.apache.spark.storage.RDDBlockId import org.apache.spark.util.SnappyUtils import org.apache.spark.{Logging, SparkEnv} @@ -52,7 +52,9 @@ import org.apache.spark.{Logging, SparkEnv} /** * Encapsulates a Spark execution for use in query routing from JDBC. */ -class SparkSQLExecuteImpl(val sql: String, +class SparkSQLExecuteImpl( + val dfObject: AnyRef, + val sql: String, val schema: String, val ctx: LeadNodeExecutionContext, senderVersion: Version, @@ -79,7 +81,8 @@ class SparkSQLExecuteImpl(val sql: String, session.setPreparedQuery(preparePhase = false, pvs) - private[this] val df = Utils.sqlInternal(session, sql) + private[this] val df = if (dfObject != null) dfObject.asInstanceOf[CachedDataFrame] + else Utils.sqlInternal(session, sql) private[this] val thresholdListener = Misc.getMemStore.thresholdListener() diff --git a/cluster/src/main/scala/io/snappydata/remote/interpreter/RemoteInterpreterStateHolder.scala b/cluster/src/main/scala/io/snappydata/remote/interpreter/RemoteInterpreterStateHolder.scala index 5b2a0bfcee..5f86dcf8cd 100644 --- a/cluster/src/main/scala/io/snappydata/remote/interpreter/RemoteInterpreterStateHolder.scala +++ b/cluster/src/main/scala/io/snappydata/remote/interpreter/RemoteInterpreterStateHolder.scala @@ -27,7 +27,7 @@ import com.pivotal.gemfirexd.internal.engine.Misc import io.snappydata.gemxd.SnappySessionPerConnection import org.apache.spark.SparkContext import org.apache.spark.repl.SparkILoop -import org.apache.spark.sql.SnappySession +import org.apache.spark.sql.{CachedDataFrame, SnappySession} import scala.collection.mutable import scala.tools.nsc.Settings @@ -69,11 +69,12 @@ class RemoteInterpreterStateHolder(val connId: Long, val user: String, val authT var incomplete = new mutable.StringBuilder() val resultBuffer = new mutable.ArrayBuffer[String]() - def interpret(code: Array[String]): Array[String] = { - return interpret(code, false) + def interpret(code: Array[String], options: Map[String, String]): AnyRef = { + return interpret(code, false, options) } - def interpret(code: Array[String], replay: Boolean): Array[String] = { + def interpret(code: Array[String], replay: Boolean, + options: Map[String, String] = null): AnyRef = { this.resultBuffer.clear() pw.reset() if (code != null && !code.isEmpty && code(0).trim.startsWith(":")) { @@ -109,7 +110,19 @@ class RemoteInterpreterStateHolder(val connId: Long, val user: String, val authT incomplete.append(tmpsb.toString()) resultBuffer += "___INCOMPLETE___" } - resultBuffer.toArray + if (options != null && options.nonEmpty && + options.isDefinedAt(RemoteInterpreterStateHolder.optionDF)) { + var allRequests = intp.prevRequestList.reverse + while (allRequests.nonEmpty) { + var request = allRequests.head + val x = request.lineRep.evalEither.right.get + if (x != null && x.isInstanceOf[CachedDataFrame]) { + if (x.asInstanceOf[CachedDataFrame].schema.fields.nonEmpty) return x + } + allRequests = allRequests.tail + } + } + resultBuffer.toArray.flatMap(_.split("\n")) } def processCommand(command: String): Array[String] = { @@ -247,6 +260,10 @@ class RemoteInterpreterStateHolder(val connId: Long, val user: String, val authT } } +object RemoteInterpreterStateHolder { + private val optionDF = "returnDF" +} + class RemoteILoop(spw: StringPrintWriter, intpHelper: RemoteInterpreterStateHolder) extends SparkILoop(null.asInstanceOf[BufferedReader], new PrintWriter(spw)) { diff --git a/cluster/src/main/scala/io/snappydata/remote/interpreter/SnappyInterpreterExecute.scala b/cluster/src/main/scala/io/snappydata/remote/interpreter/SnappyInterpreterExecute.scala index 7f5436cde0..2b79428fd0 100644 --- a/cluster/src/main/scala/io/snappydata/remote/interpreter/SnappyInterpreterExecute.scala +++ b/cluster/src/main/scala/io/snappydata/remote/interpreter/SnappyInterpreterExecute.scala @@ -36,7 +36,7 @@ import scala.collection.mutable class SnappyInterpreterExecute(sql: String, connId: Long) extends InterpreterExecute with Logging { - override def execute(user: String, authToken: String): Array[String] = { + override def execute(user: String, authToken: String): AnyRef = { if (!SnappyInterpreterExecute.INITIALIZED) SnappyInterpreterExecute.init() val (allowed, group) = SnappyInterpreterExecute.permissions.isAllowed(user) if (Misc.isSecurityEnabled && !user.equalsIgnoreCase(SnappyInterpreterExecute.dbOwner)) { @@ -49,9 +49,11 @@ class SnappyInterpreterExecute(sql: String, connId: Long) extends InterpreterExe val session = SnappySessionPerConnection.getSnappySessionForConnection(connId) val lp = session.sessionState.sqlParser.parsePlan(sql).asInstanceOf[InterpretCodeCommand] val interpreterHelper = SnappyInterpreterExecute.getOrCreateStateHolder(connId, user, authToken, group) - val outputLines = interpreterHelper.interpret(lp.code.split("\n")) - if (outputLines != null && outputLines.nonEmpty) outputLines.flatMap(_.split("\n")) - else outputLines + try { + interpreterHelper.interpret(lp.code.split("\n"), lp.options) + } finally { + scala.Console.setOut(System.out) + } } } diff --git a/core/src/test/scala/io/snappydata/CommandLineToolsSuite.scala b/core/src/test/scala/io/snappydata/CommandLineToolsSuite.scala index 07683f07aa..1aa8972527 100644 --- a/core/src/test/scala/io/snappydata/CommandLineToolsSuite.scala +++ b/core/src/test/scala/io/snappydata/CommandLineToolsSuite.scala @@ -34,6 +34,154 @@ class CommandLineToolsSuite extends SnappyTestRunner { private val snappyProductDir = System.getenv("SNAPPY_HOME") private val snappyNativeTestDir = s"$snappyProductDir/../../../store/native/tests" + test("exec scala") { + val conn = getJdbcConnection(1527) + val stmnt = conn.createStatement() + val cmdOutput = "exec-scala-output.txt" + try { + SnappyShell("quickStartScripts", Seq("connect client 'localhost:1527';", + s"create table test_app (col1 int not null, col2 int not null) using column options();;", + s"insert into test_app values (1, 1), (2, 2);", + s"insert into test_app values (5, 3), (6, 4);", + "exit;"), cmdOutput) + val conn = getJdbcConnection(1527) + val stmnt = conn.createStatement() + assert(stmnt.execute("select * from test_app")) + val rs1 = stmnt.getResultSet + var cnt = 0 + while (rs1.next()) { + cnt = cnt + 1 + val v1 = rs1.getInt(1) + rs1.getInt(2) + assert(v1 === 1 || v1 === 2 || v1 === 5 || v1 === 6) + } + assert(cnt === 4) + // Now execute some exec scala and verify from connection itself + assert(stmnt.execute("exec scala snappy.sql(\"insert into test_app values(10, 10), (20, 20)\")")) + var rs = stmnt.getResultSet + assert(rs.next()) + assert(stmnt.execute("exec scala snappy.sql(\"create table test_exec(col1 int not null, col2 int not null)\")")) + rs = stmnt.getResultSet + // insert few rows from jdbc connection itself + stmnt.execute("insert into test_exec values(1000, 1000), (2000, 2000)") + assert(stmnt.execute("exec scala val df1 = snappy.table(\"test_app\")\n" + + "// Let's union two dfs and save the union as another table\n" + + "val df2 = snappy.table(\"test_exec\")\n" + + "val df3 = df1.union(df2)\n" + + "df3.show")) + stmnt.execute("exec scala options(returnDF 'true') snappy.table(\"test_exec\")") + rs = stmnt.getResultSet + assert(rs.next()) + // expected count is 1 because .table api returns DataSet and exec scala needs cached dataframe + // to return result + assert(rs.getMetaData.getColumnCount == 1) + assert(stmnt.execute("exec scala options(returnDF 'true') snappy.sql(\"select * from test_exec\")")) + rs = stmnt.getResultSet + assert(rs.next()) + assert(rs.getMetaData.getColumnCount == 2) + assert(stmnt.execute("exec scala snappy.sql(\"delete from test_exec\")")) + assert(stmnt.execute("select * from test_exec")) + rs = stmnt.getResultSet + assert(!rs.next()) + } finally { + // do cleanup + stmnt.execute("drop table if exists test_app") + stmnt.execute("drop table if exists test_exec") + } + } + + test("snappy scala") { +// val scala_code1 = Seq( +// "case class TestData(c1: Int, c2: String)", +// " var rdd = sc.parallelize(", +// " (1 to 10).map(i => TestData(i, i.toString)))", +// " val dataDF = snappy.createDataFrame(rdd)", +// " val tablename = \"testtable\"", +// " dataDF.write.insertInto(tableName)", +// ":qu" +// ) + val scala_code1 = Seq( + "case class TestData(c1: Int, c2: String)", + "val x = TestData(1, \"1\")", + "snappy.sql(\"create table tmptable(c1 int not null, c2 string)\")", + "snappy.sql(\"insert into tmptable values(1, \'1\')\")", + ":qu" + ) + val conn = getJdbcConnection(1527) + val stmnt = conn.createStatement() + val cmdOutput = "snappyscala-output.txt" + try { + SnappyScalaShell("scala_code", scala_code1, cmdOutput) + stmnt.execute("create table testtable as select * from tmptable") + assert(stmnt.execute("select count(*) from testtable")) + var rs = stmnt.getResultSet + assert(rs.next()) + assert(rs.getInt(1) == 1) + } finally { + stmnt.execute("drop table if exists testtable") + stmnt.execute("drop table if exists tmptable") + } + } + + test("snappy scala run") { + val scala_code1 = Seq( + "snappy.sql(\"create table tmptable(c1 int not null, c2 string)\")", + "snappy.sql(\"insert into tmptable values(1, \'1\')\")", + ":qu" + ) + val scala_code2 = Seq( + "snappy.sql(\"create table tmptable2(c1 int not null, c2 string)\")", + "snappy.sql(\"insert into tmptable2 values(1, \'1\')\")", + ":qu" + ) + val scala_code3 = Seq( + "snappy.sql(\"create table tmptable3(c1 int not null, c2 string)\")", + "snappy.sql(\"insert into tmptable3 values(1, \'1\')\")", + ":qu" + ) + val conn = getJdbcConnection(1527) + val stmnt = conn.createStatement() + val cmdOutput = "snappyscala-output.txt" + val scalaFileToRun1 = "snappyrun1.scala" + val scalaFileToRun2 = "snappyrun2.scala" + val scalaFileToRun3 = "snappyrun3.scala" + try { + Seq(scalaFileToRun1, scalaFileToRun2, scalaFileToRun3).zip( + Seq(scala_code1, scala_code2, scala_code3)).foreach(x => { + val file = new File(x._1) + val printWriter = new PrintWriter(file) + x._2.foreach(s => { + printWriter.write(s) + printWriter.write("\n") + }) + printWriter.close() + }) + + SnappyScalaShell("scala_code", scala_code1, cmdOutput, + s"$snappyscalaShell -r $scalaFileToRun1") + stmnt.execute("create table testtable as select * from tmptable") + assert(stmnt.execute("select count(*) from testtable")) + var rs = stmnt.getResultSet + assert(rs.next()) + assert(rs.getInt(1) == 1) + + // Two files + SnappyScalaShell("scala_code", scala_code1, cmdOutput, + s"$snappyscalaShell -r $scalaFileToRun2,$scalaFileToRun3") + assert(stmnt.execute("select count(*) from tmptable2")) + rs = stmnt.getResultSet + assert(rs.next()) + assert(rs.getInt(1) == 1) + assert(stmnt.execute("select count(*) from tmptable3")) + rs = stmnt.getResultSet + assert(rs.next()) + assert(rs.getInt(1) == 1) + } finally { + stmnt.execute("drop table if exists testtable") + stmnt.execute("drop table if exists tmptable") + } + } + // scalastyle:off println test("backup restore") { val debugWriter = new PrintWriter(s"$snappyHome/CommandLineToolsSuite.debug") @@ -47,7 +195,7 @@ class CommandLineToolsSuite extends SnappyTestRunner { s" using row options(DISKSTORE 'GFXD-DD-DISKSTORE');", s"insert into testDD values (1, 1), (2, 2);", s"insert into testDD values (5, 3), (6, 4);", - "exit;")) + "exit;"), commandOutput) if (backupDir.exists) { assert(backupDir.delete(), s"could not delete $backupDir") diff --git a/examples/src/test/scala/io/snappydata/SnappyTestRunner.scala b/examples/src/test/scala/io/snappydata/SnappyTestRunner.scala index 2d34d34012..fd237f65a9 100644 --- a/examples/src/test/scala/io/snappydata/SnappyTestRunner.scala +++ b/examples/src/test/scala/io/snappydata/SnappyTestRunner.scala @@ -49,7 +49,7 @@ with Logging with Retries { var snappyHome = "" var localHostName = "" var currWorkingDir = "" - private val commandOutput = "command-output.txt" + protected val commandOutput = "command-output.txt" // One can ovveride this method to pass other parameters like heap size. def servers: String = s"$localHostName\n$localHostName" @@ -60,6 +60,8 @@ with Logging with Retries { def sparkShell: String = s"$snappyHome/bin/spark-shell" + def snappyscalaShell: String = s"$snappyHome/bin/snappy-scala" + def clusterSuccessString: String = "Distributed system now has 4 members" private val availablePort = AvailablePort.getRandomAvailablePort(AvailablePort.JGROUPS) @@ -156,9 +158,9 @@ with Logging with Retries { } - def SnappyShell(name: String, sqlCommand: Seq[String]): Unit = { + def SnappyShell(name: String, sqlCommand: Seq[String], cmdOutput: String): Unit = { val writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter( - new FileOutputStream(commandOutput, true)))) + new FileOutputStream(cmdOutput, true)))) try { sqlCommand pipe snappyShell foreach (s => { writer.println(s) @@ -171,6 +173,22 @@ with Logging with Retries { } } + def SnappyScalaShell(name: String, scalaLines: Seq[String], cmdOutput: String, + cliWithArgs: String = snappyscalaShell): Unit = { + val writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter( + new FileOutputStream(cmdOutput, true)))) + try { + scalaLines pipe cliWithArgs foreach (s => { + writer.println(s) + if (s.toString.contains("ERROR") || s.toString.contains("Failed")) { + throw new Exception(s"Failed to run Query: $s") + } + }) + } finally { + writer.close() + } + } + def Job(jobClass: String, lead: String, jarPath: String, confs: Seq[String] = Nil): Unit = { diff --git a/examples/src/test/scala/io/snappydata/quickstart/ExampleTestSuite.scala b/examples/src/test/scala/io/snappydata/quickstart/ExampleTestSuite.scala index 583d05e158..2eb1a0a660 100644 --- a/examples/src/test/scala/io/snappydata/quickstart/ExampleTestSuite.scala +++ b/examples/src/test/scala/io/snappydata/quickstart/ExampleTestSuite.scala @@ -40,7 +40,7 @@ class ExampleTestSuite extends SnappyTestRunner { s"run '$snappyHome/quickstart/scripts/oltp_queries.sql';", s"run '$snappyHome/quickstart/scripts/olap_queries.sql';", s"run '$snappyHome/quickstart/scripts/olap_approx_queries.sql';", - "exit;")) + "exit;"), commandOutput) Job("io.snappydata.examples.AirlineDataJob", localLead, quickStartJar) @@ -126,7 +126,7 @@ class ExampleTestSuite extends SnappyTestRunner { s"CREATE TABLE SNAPPY_COL_TABLE(r1 Integer, r2 Integer) USING COLUMN;", s"insert into SNAPPY_COL_TABLE VALUES(1,1);", s"insert into SNAPPY_COL_TABLE VALUES(2,2);", - "exit;")) + "exit;"), commandOutput) RunExample("SmartConnectorExample", "snappydata.SmartConnectorExample", From 159122d8edb8d7731f7c743e50c2eb4ee6aae96a Mon Sep 17 00:00:00 2001 From: Neeraj Kumar Date: Thu, 28 Nov 2019 17:33:09 +0530 Subject: [PATCH 025/101] Linking the latest store. --- store | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/store b/store index 68d5ead5f6..eebc6f318f 160000 --- a/store +++ b/store @@ -1 +1 @@ -Subproject commit 68d5ead5f6b15c4c2e8b19ba6584b0f4a57fe85b +Subproject commit eebc6f318f72520ae287a6ffff914b5a356cbc66 From 47df39ae5351b60eb37cf544573bb3484fc37efe Mon Sep 17 00:00:00 2001 From: Amogh Shetkar Date: Fri, 29 Nov 2019 10:32:00 +0530 Subject: [PATCH 026/101] [SNAP-3229] Changing default config in launch scripts for user convenience. (#1475) * Set client-bind-address to 0.0.0.0 by default on AWS, unless explicitly specified by user. * Directly invoke individual launch script without ssh even if the hostname in conf file is not localhost but is an IP of the same host. Thus, not requiring the passwordless ssh, in such cases. * Remove VSD from the product build. --- build.gradle | 34 ++-------------------------------- cluster/bin/snappy | 23 ++++++++++++++++------- cluster/sbin/snappy-nodes.sh | 6 +++--- 3 files changed, 21 insertions(+), 42 deletions(-) diff --git a/build.gradle b/build.gradle index 2ac3fb3bbe..a75c1350e8 100644 --- a/build.gradle +++ b/build.gradle @@ -72,7 +72,7 @@ allprojects { apply plugin: "build-time-tracker" group = 'io.snappydata' - version = '1.1.1' + version = '1.2-SNAPSHOT' // apply compiler options tasks.withType(JavaCompile) { @@ -151,7 +151,7 @@ allprojects { antlr2Version = '2.7.7' pegdownVersion = '1.6.0' - snappyStoreVersion = '1.6.4' + snappyStoreVersion = '1.6.5-SNAPSHOT' snappydataVersion = version pulseVersion = '1.5.1' zeppelinInterpreterVersion = '0.7.3.6' @@ -1200,7 +1200,6 @@ ospackage { } buildRpm { - dependsOn ':packageVSD' if (rootProject.hasProperty('enablePublish')) { dependsOn ':packageZeppelinInterpreter' } @@ -1216,7 +1215,6 @@ buildRpm { } buildDeb { - dependsOn ':packageVSD' if (rootProject.hasProperty('enablePublish')) { dependsOn ':packageZeppelinInterpreter' } @@ -1241,7 +1239,6 @@ distTar { } dependsOn product // also package VSD - dependsOn ':packageVSD' if (rootProject.hasProperty('enablePublish')) { dependsOn ':packageZeppelinInterpreter' } @@ -1261,7 +1258,6 @@ distZip { } dependsOn product // also package VSD - dependsOn ':packageVSD' if (rootProject.hasProperty('enablePublish')) { dependsOn ':packageZeppelinInterpreter' } @@ -1489,37 +1485,11 @@ task packagePulse { doLast { } } } -task packageVSD { doLast { - String thirdparty = System.env.THIRDPARTYDIR - String vsdDir = '' - - if (thirdparty == null || thirdparty.length() == 0) { - vsdDir = "${projectDir}/../thirdparty/vsd" - } else { - vsdDir = "${thirdparty}/vsd" - } - - String vsdDistDir = "${vsdDir}/70/vsd" - if (file(vsdDistDir).canWrite()) { - println '' - println "Copying VSD from ${vsdDistDir} to ${snappyProductDir}/vsd" - println '' - delete "${snappyProductDir}/vsd" - copy { - from vsdDistDir - into "${snappyProductDir}/vsd" - } - } else { - println "Skipping VSD due to unwritable ${vsdDistDir}" - } -} } - task sparkPackage { dependsOn ":snappy-core_${scalaBinaryVersion}:sparkPackage" } packagePulse.mustRunAfter product -packageVSD.mustRunAfter product packageZeppelinInterpreter.mustRunAfter product distTar.mustRunAfter clean, cleanAll, product diff --git a/cluster/bin/snappy b/cluster/bin/snappy index e330103020..e6f4865118 100755 --- a/cluster/bin/snappy +++ b/cluster/bin/snappy @@ -76,9 +76,10 @@ elif [ -z "$SNAPPY_NO_QUICK_LAUNCH" -a $# -ge 2 \ . "${SPARK_HOME}"/bin/load-snappy-env.sh HOSTNAME_FOR_CLIENTS= + IMPLICIT_AWS_CLIENT_BIND_ADDRESS= if [ "$2" = "start" ]; then # set hostname-for-clients and SPARK_PUBLIC_DNS in AWS (only supported for Linux) - if [ -z "$SPARK_PUBLIC_DNS" ]; then + if [ -z "$SPARK_PUBLIC_DNS" -o -n "$IMPLICIT_CLIENT_BIND_ADDRESS" ]; then CHECK_AWS=1 if [ -r /sys/hypervisor/uuid ]; then if ! grep -q '^ec2' /sys/hypervisor/uuid; then @@ -93,19 +94,27 @@ elif [ -z "$SNAPPY_NO_QUICK_LAUNCH" -a $# -ge 2 \ CHECK_AWS= fi if [ -n "$CHECK_AWS" ]; then - SPARK_PUBLIC_DNS="$(curl -s --connect-timeout 3 http://169.254.169.254/latest/meta-data/public-ipv4 | head -1)" - if [ -n "$SPARK_PUBLIC_DNS" ]; then - if ! echo $"${@// /\\ }" | grep -q 'hostname-for-clients='; then - HOSTNAME_FOR_CLIENTS="-hostname-for-clients=$SPARK_PUBLIC_DNS" + if [ -z "$SPARK_PUBLIC_DNS" ]; then + SPARK_PUBLIC_DNS="$(curl -s --connect-timeout 3 http://169.254.169.254/latest/meta-data/public-ipv4 | head -1)" + if [ -n "$SPARK_PUBLIC_DNS" ]; then + if ! echo $"${@// /\\ }" | grep -q 'hostname-for-clients='; then + HOSTNAME_FOR_CLIENTS="-hostname-for-clients=$SPARK_PUBLIC_DNS" + fi + export SPARK_PUBLIC_DNS fi - export SPARK_PUBLIC_DNS fi + if [ -n "$IMPLICIT_CLIENT_BIND_ADDRESS" ]; then + IMPLICIT_AWS_CLIENT_BIND_ADDRESS="-client-bind-address=0.0.0.0" + fi + else + IMPLICIT_AWS_CLIENT_BIND_ADDRESS="-client-bind-address=${IMPLICIT_CLIENT_BIND_ADDRESS}" fi fi fi JARS="`echo "${SPARK_HOME}"/jars/snappydata-launcher* "${SPARK_HOME}"/jars/gemfire-shared* "${SPARK_HOME}"/jars/jna-4.* | sed 's/ /:/g'`" - exec $RUNNER $JAVA_ARGS -Xverify:none -cp "$JARS" io.snappydata.tools.QuickLauncher "$@" $HOSTNAME_FOR_CLIENTS + exec $RUNNER $JAVA_ARGS -Xverify:none -cp "$JARS" io.snappydata.tools.QuickLauncher "$@" $HOSTNAME_FOR_CLIENTS $IMPLICIT_AWS_CLIENT_BIND_ADDRESS + IMPLICIT_CLIENT_BIND_ADDRESS= else # use full snappy launcher exec "$SPARK_HOME"/bin/spark-class $JAVA_ARGS io.snappydata.tools.SnappyUtilLauncher "$@" diff --git a/cluster/sbin/snappy-nodes.sh b/cluster/sbin/snappy-nodes.sh index d287209835..41ac0b3432 100755 --- a/cluster/sbin/snappy-nodes.sh +++ b/cluster/sbin/snappy-nodes.sh @@ -201,8 +201,8 @@ function execute() { # set the default client-bind-address and locator's peer-discovery-address if [ -z "${clientBindAddress}" -a "${componentType}" != "lead" ]; then - args="${args} -client-bind-address=${host}" - clientBindAddress="${host}" + preCommand="${preCommand}export IMPLICIT_CLIENT_BIND_ADDRESS=$host; " + export IMPLICIT_CLIENT_BIND_ADDRESS="${host}" fi if [ -z "$(echo $args $"${@// /\\ }" | grep 'peer-discovery-address=')" -a "${componentType}" = "locator" ]; then args="${args} -peer-discovery-address=${host}" @@ -243,7 +243,7 @@ function execute() { -*) postArgs="$postArgs $arg" esac done - if [ "$host" != "localhost" ]; then + if [ "$host" != "localhost" -a -n "$(echo `hostname -I` | grep -q "$host")" ]; then if [ "$dirfolder" != "" ]; then # Create the directory for the snappy component if the folder is a default folder (ssh $SPARK_SSH_OPTS "$host" \ From 8d962ca9ea3105c2fc1c9a0634245df1e3ebbdb7 Mon Sep 17 00:00:00 2001 From: paresh-p11 <43569032+paresh-p11@users.noreply.github.com> Date: Fri, 29 Nov 2019 10:56:56 +0530 Subject: [PATCH 027/101] [SNAP-3246] - (#1489) * [SNAP-3246] - Adding support for CHAR data type Added tests and minor refactoring --- .../cluster/PrimaryDUnitRecoveryTest.scala | 57 ++++++++++++------- .../sql/execution/oplog/impl/OpLogRdd.scala | 3 + spark | 2 +- 3 files changed, 39 insertions(+), 23 deletions(-) diff --git a/cluster/src/dunit/scala/io/snappydata/cluster/PrimaryDUnitRecoveryTest.scala b/cluster/src/dunit/scala/io/snappydata/cluster/PrimaryDUnitRecoveryTest.scala index 3425b0c2ed..020f599a8a 100644 --- a/cluster/src/dunit/scala/io/snappydata/cluster/PrimaryDUnitRecoveryTest.scala +++ b/cluster/src/dunit/scala/io/snappydata/cluster/PrimaryDUnitRecoveryTest.scala @@ -193,14 +193,14 @@ class PrimaryDUnitRecoveryTest(s: String) extends DistributedTestBase(s) // scal s" (null,null,333.333, null, 'true')") // data only in column batches - not in row buffers - nulls in data - column table - stmt.execute(s"CREATE TABLE $defaultSchema.test1coltab7 (col1 Bigint, col2 varchar(44), col3" + + stmt.execute(s"CREATE TABLE $defaultSchema.test1coltab7 (col1 Bigint, col2 char(2), col3" + s" double,col4 byte,col5 date)USING COLUMN OPTIONS(buckets '2',COLUMN_MAX_DELTA_ROWS '3')") stmt.execute(s"INSERT INTO $defaultSchema.test1coltab7" + - s" VALUES(9123372036812312307, 'asdfwerq334',123.123324, 12,'2019-03-20')") + s" VALUES(9123372036812312307, 'aa',123.123324, 12,'2019-03-20')") stmt.execute(s"INSERT INTO $defaultSchema.test1coltab7 " + - s"VALUES(null, 'qewrqewr4',345.123324, 11,'2019-03-21')") + s"VALUES(null, 'bb',345.123324, 11,'2019-03-21')") stmt.execute(s"INSERT INTO $defaultSchema.test1coltab7 " + - s"VALUES(8123372036812312307, 'asdfwerq334',null, null, null)") + s"VALUES(8123372036812312307, 'cc',null, null, null)") // data in only row buffer of column table - nulls in data stmt.execute(s"CREATE TABLE $defaultSchema.test1coltab8 (col1 Bigint, col2 varchar(44), col3" + @@ -676,9 +676,9 @@ class PrimaryDUnitRecoveryTest(s: String) extends DistributedTestBase(s) // scal " gemfire10.test1coltab7 ORDER BY col1") arrBuf.clear() i = 0 - arrBuf ++= ArrayBuffer("NULL,qewrqewr4,345.123324,11,2019-03-21", - "8123372036812312307,asdfwerq334,NULL,NULL,NULL", - "9123372036812312307,asdfwerq334,123.123324,12,2019-03-20") + arrBuf ++= ArrayBuffer("NULL,bb,345.123324,11,2019-03-21", + "8123372036812312307,cc,NULL,NULL,NULL", + "9123372036812312307,aa,123.123324,12,2019-03-20") while (rs.next()) { str.clear() str ++= s"${rs.getObject(1)},${rs.getObject(2)},${rs.getObject(3)}," + @@ -713,9 +713,10 @@ class PrimaryDUnitRecoveryTest(s: String) extends DistributedTestBase(s) // scal } catch { case e: Throwable => - afterEach() test_status = false throw new Exception(e) + } finally { + afterEach() } } @@ -747,6 +748,8 @@ class PrimaryDUnitRecoveryTest(s: String) extends DistributedTestBase(s) // scal | confdirpath: $confDirPath | ldapConf: $ldapConf""".stripMargin) + // todo: test with 2 locators + writeToFile(s"localhost -peer-discovery-port=$locatorPort -recovery-state-chunk-size=20 -dir=$workDirPath/locator-1" + s" -client-port=$locNetPort $ldapConf", s"$confDirPath/locators") writeToFile(s"localhost -locators=localhost[$locatorPort] -dir=$workDirPath/lead-1" + @@ -764,7 +767,6 @@ class PrimaryDUnitRecoveryTest(s: String) extends DistributedTestBase(s) // scal conn = getConn(locNetPort, "gemfire10", "gemfire10") stmt = conn.createStatement() - // todo: add binary and blob stmt.execute( s"""CREATE TABLE gemfire10.test3tab1 (col1 BIGINT NOT NULL, col2 INT NOT NULL, col3 INTEGER NOT NULL, @@ -772,7 +774,7 @@ class PrimaryDUnitRecoveryTest(s: String) extends DistributedTestBase(s) // scal col7 byte NOT NULL, c1 tinyint NOT NULL, c2 varchar(22) NOT NULL, c3 string NOT NULL, c5 boolean NOT NULL,c6 double NOT NULL, c8 timestamp NOT NULL, c9 date NOT NULL, c10 decimal(15,5) NOT NULL, c11 numeric(20,10) NOT NULL, - c12 float NOT NULL,c13 real not null, c14 binary, c15 blob, c16 clob) USING COLUMN + c12 float NOT NULL,c13 real not null, c14 binary, c15 blob, c16 clob, c17 char(1)) USING COLUMN OPTIONS (BUCKETS '5', COLUMN_MAX_DELTA_ROWS '135'); """) @@ -780,7 +782,7 @@ class PrimaryDUnitRecoveryTest(s: String) extends DistributedTestBase(s) // scal s"""INSERT INTO gemfire10.test3tab1 select 9123372036854775807,2117483647,2116483647, 8223372036854775807,72,13,5,5,'qwerqwerqwer','qewrqewr',false,912384020490234.91928374997239749824, '2019-02-18 15:31:55.333','2019-02-18',2233.67234,4020490234.7239749824, - 912384020490234.91928374997239749824,920490234.9192837499724, cast ('aaa' as binary), cast('2234' as blob), cast('adsf' as clob)""".stripMargin) + 912384020490234.91928374997239749824,920490234.9192837499724, cast ('aaa' as binary), cast('2234' as blob), cast('adsf' as clob), 'b'""".stripMargin) stmt.execute("INSERT INTO gemfire10.test3tab1 select id*100000000000000,id,id*100000000" + ",id*100000000000000,id,id, cast(id as byte), cast(id as tinyint)" + @@ -788,7 +790,7 @@ class PrimaryDUnitRecoveryTest(s: String) extends DistributedTestBase(s) // scal ", cast(id%2 as Boolean), cast((id*701*7699 + id*1342341*2267)/2 as double)" + ", CURRENT_TIMESTAMP, CURRENT_DATE, cast(id*241/11 as Decimal(15,5))" + ", cast(id*701/11 as Numeric(20,10)), cast(concat(id*100,'.',(id+1)*7699) as float)" + - ", cast(concat(id*100000000000,'.',(id+1)*2267*7699) as real), cast('binary_'|| id as binary), cast('blob_' || id as blob), cast(id*2 as clob) from range(500);") + ", cast(concat(id*100000000000,'.',(id+1)*2267*7699) as real), cast('binary_'|| id as binary), cast('blob_' || id as blob), cast(id*2 as clob), 'a' from range(500);") val rsTest3tab1 = stmt.executeQuery("SELECT * FROM gemfire10.test3tab1 ORDER BY col2") compareResultSet("gemfire10.test3tab1", rsTest3tab1, false) @@ -799,7 +801,7 @@ class PrimaryDUnitRecoveryTest(s: String) extends DistributedTestBase(s) // scal col5 short , col6 smallint , col7 byte , c1 tinyint , c2 varchar(22) , c3 string , c5 boolean ,c6 double , c8 timestamp , c9 date , c10 decimal(15,5) , c11 numeric(20,10) , - c12 float ,c13 float + c12 float ,c13 float, c14 char(3) , primary key (col2,col3)) using row options (partition_by 'col1,col2,col3', buckets '5', COLUMN_MAX_DELTA_ROWS '135'); @@ -809,7 +811,7 @@ class PrimaryDUnitRecoveryTest(s: String) extends DistributedTestBase(s) // scal s"""INSERT INTO gemfire10.test3tab2 VALUES(9123372036854775807,2117483647,2116483647, 8223372036854775807,72,13,5,5,'qwerqwerqwer','qewrqewr',false,912384020490234.91928374997239749824, '2019-02-18 15:31:55.333','2019-02-18',2233.67234,4020490234.7239749824, - 912384020490234.91928374997239749824,920490234.9192837499724)""".stripMargin) + 912384020490234.91928374997239749824,920490234.9192837499724, 'abc')""".stripMargin) stmt.execute( s"""INSERT INTO gemfire10.test3tab2 select id*100000000000000,id,id*100000000,id*100000000000000,id,id, @@ -818,7 +820,7 @@ class PrimaryDUnitRecoveryTest(s: String) extends DistributedTestBase(s) // scal | cast(id%2 as Boolean), cast((id*701*7699 + id*1342341*2267)/2 as double), CURRENT_TIMESTAMP, | CURRENT_DATE, cast(id*241/11 as Decimal(15,5)), cast(id*701/11 as Numeric(20,10)), | cast(concat(id*100,'.',(id+1)*7699) as float), - | cast(concat(id*100000000000,'.',(id+1)*2267*7699) as real) from range(5); + | cast(concat(id*100000000000,'.',(id+1)*2267*7699) as real), 'asd' from range(5); | """.stripMargin) @@ -833,7 +835,7 @@ class PrimaryDUnitRecoveryTest(s: String) extends DistributedTestBase(s) // scal c2 varchar(22) , c3 string , c5 boolean , c6 double , c8 timestamp , c9 date not null, c10 decimal(15,5) , c11 numeric(12,4) not null, c12 float ,c13 real not null, c14 binary, - c15 blob, primary key (col2)) using row + c15 blob, c16 char(4), primary key (col2)) using row options (); """) stmt.execute( @@ -845,7 +847,7 @@ class PrimaryDUnitRecoveryTest(s: String) extends DistributedTestBase(s) // scal cast(id*241/11 as Decimal(15,5)), cast(id*701/11 as Numeric(12,4)), cast(concat(id*100,'.',(id+1)*7699) as float), cast(concat(id*100000000000,'.',(id+1)*2267*7699) as real), cast('aaaa' as binary), - cast('yyyy' as blob) from range(5); + cast('yyyy' as blob), 'asdf' from range(5); """.stripMargin) val rsTest3Reptab2 = stmt.executeQuery("SELECT * FROM gemfire10.test3Reptab2 ORDER BY col2") @@ -1101,9 +1103,10 @@ class PrimaryDUnitRecoveryTest(s: String) extends DistributedTestBase(s) // scal test_status = true } catch { case e: Throwable => - afterEach() test_status = false throw new Exception(e) + } finally { + afterEach() } } @@ -1140,7 +1143,6 @@ class PrimaryDUnitRecoveryTest(s: String) extends DistributedTestBase(s) // scal def test5(): Unit = { try { // todo: Should be able to recover data and export to S3, hdfs, nfs and local file systems. - // todo: Check performance with large volume of data. // todo: Recover data in parquet format, test that, reloading the table from the same parquet file should work fine. confDirPath = createConfDir("test5") @@ -1241,6 +1243,7 @@ class PrimaryDUnitRecoveryTest(s: String) extends DistributedTestBase(s) // scal stmt.execute("undeploy snappyjar") stmt.execute("undeploy Sparkcassandra") + stmt.execute("call sys.EXPORT_DDLS('./regularmode_ddls_test5');") stmt.close() conn.close() @@ -1292,6 +1295,14 @@ class PrimaryDUnitRecoveryTest(s: String) extends DistributedTestBase(s) // scal new File("/tmp/test5_exttab1.csv").delete() // todo: add assertion for recover_ddls +// import reflect.io._, Path._ +// "find -name recover_ddls_test5*".!!.trim.toDirectory.files.foreach(println) +// "find -name regularmode_ddls_test5*".!!.trim.toDirectory.files.foreach(println) +// +// val recoverymodeDdlFile = {for (elem <- "find -name recover_ddls_test5*".!!.trim.toDirectory.files; if(elem.name == "part-00000")) yield elem}.next() +// val regularmodeDdlFile = {for (elem <- "find -name regularmode_ddls_test5*".!!.trim.toDirectory.files; if(elem.name == "part-00000")) yield elem }.next() +// val cmd = s"comm --nocheck-order -3 ${recoverymodeDdlFile.path} ${recoverymodeDdlFile.path}" + stmtRec.close() connRec.close() @@ -1300,9 +1311,10 @@ class PrimaryDUnitRecoveryTest(s: String) extends DistributedTestBase(s) // scal } catch { case e: Throwable => - afterEach() test_status = false throw new Exception(e) + } finally { + afterEach() } } @@ -1566,7 +1578,7 @@ class PrimaryDUnitRecoveryTest(s: String) extends DistributedTestBase(s) // scal } // ********************************************* - // ******************testcase 1***************** + // ****************** testcase 1 *************** // ********************************************* val rs = stmtRec.executeQuery("select * from gemfire10.t1") val expectedResult1: ListBuffer[Array[Any]] = ListBuffer( @@ -1713,9 +1725,10 @@ class PrimaryDUnitRecoveryTest(s: String) extends DistributedTestBase(s) // scal test_status = true } catch { case e: Throwable => - afterEach() test_status = false throw new Exception(e) + } finally { + afterEach() } } } diff --git a/core/src/main/scala/org/apache/spark/sql/execution/oplog/impl/OpLogRdd.scala b/core/src/main/scala/org/apache/spark/sql/execution/oplog/impl/OpLogRdd.scala index ded8e60be2..fc8c4b0702 100644 --- a/core/src/main/scala/org/apache/spark/sql/execution/oplog/impl/OpLogRdd.scala +++ b/core/src/main/scala/org/apache/spark/sql/execution/oplog/impl/OpLogRdd.scala @@ -112,6 +112,9 @@ class OpLogRdd( case "VARCHAR" => DataTypeDescriptor.getBuiltInDataTypeDescriptor(Types.VARCHAR, isNullable, metadata.getLong("size").toInt) + case "CHAR" => + DataTypeDescriptor.getBuiltInDataTypeDescriptor(Types.CHAR, isNullable, + metadata.getLong("size").toInt) } } else { diff --git a/spark b/spark index 1cdbfb77bd..ec4f6cd87e 160000 --- a/spark +++ b/spark @@ -1 +1 @@ -Subproject commit 1cdbfb77bde9524237e7c02250c01d1f024ed5d1 +Subproject commit ec4f6cd87e527c218d785d296c8d4594f7eede55 From fe4b03a3c20cdb0f296222a9f6b2d00c1993f05b Mon Sep 17 00:00:00 2001 From: vatsal mevada Date: Fri, 29 Nov 2019 12:04:01 +0530 Subject: [PATCH 028/101] [SNAP-3249] Incrementing catalog version only when table is created (#1487) In order to populate primary key details for row tables in catalog, we are fetching the same detail from Gemfire layer after table creation is done. This additional alter table (to add primary key details) was earlier performed while running creting table query even if table was already existing. With this chances we are doing it only if table was not already existing. --- .../org/apache/spark/sql/SnappySession.scala | 35 +++++-- .../spark/sql/store/CatalogVersionTest.scala | 96 +++++++++++++++++++ 2 files changed, 121 insertions(+), 10 deletions(-) create mode 100644 core/src/test/scala/org/apache/spark/sql/store/CatalogVersionTest.scala diff --git a/core/src/main/scala/org/apache/spark/sql/SnappySession.scala b/core/src/main/scala/org/apache/spark/sql/SnappySession.scala index 6af5fd24f2..6e0f698b62 100644 --- a/core/src/main/scala/org/apache/spark/sql/SnappySession.scala +++ b/core/src/main/scala/org/apache/spark/sql/SnappySession.scala @@ -1371,8 +1371,8 @@ class SnappySession(_sc: SparkContext) extends SparkSession(_sc) { } // check for permissions in the schema which should be done before the session catalog // createTable call since store table will be created by that time - val resolvedName = sessionCatalog.resolveTableIdentifier(tableIdent) - sessionCatalog.checkSchemaPermission(resolvedName.database.get, resolvedName.table, + val resolvedIdentifier = sessionCatalog.resolveTableIdentifier(tableIdent) + sessionCatalog.checkSchemaPermission(resolvedIdentifier.database.get, resolvedIdentifier.table, defaultUser = null, ignoreIfNotExists = true) val schema = userSpecifiedSchema match { @@ -1411,7 +1411,7 @@ class SnappySession(_sc: SparkContext) extends SparkSession(_sc) { case None => { // case when create api was used - sql text cannot be captured in this case. userSpecifiedSchema match { - case Some(schema) => s"create table ${resolvedName.table} (${getDDLSchema(schema)})" + case Some(schema) => s"create table ${resolvedIdentifier.table} (${getDDLSchema(schema)})" case None => "" } } @@ -1430,7 +1430,7 @@ class SnappySession(_sc: SparkContext) extends SparkSession(_sc) { } val tableDesc = CatalogTable( - identifier = resolvedName, + identifier = resolvedIdentifier, tableType = tableType, storage = storage, schema = schema, @@ -1439,19 +1439,32 @@ class SnappySession(_sc: SparkContext) extends SparkSession(_sc) { partitionColumnNames = partitionColumns, bucketSpec = bucketSpec) val plan = CreateTable(tableDesc, mode, query.map(MarkerForCreateTableAsSelect)) + + // Checking whether table already exist before executing create table plan. This flag is later + // used to decide whether to populate primary keys or not. i.e. if the table was already + // existing then we skip the step to alter table in catalog to populate primary key + // information to avoid unnecessary catalog version increment. + val tableAlreadyExisted = sessionState.catalog.tableExists(resolvedIdentifier) sessionState.executePlan(plan).toRdd - val df = table(resolvedName) + val df = table(resolvedIdentifier) val relation = df.queryExecution.analyzed.collectFirst { case l: LogicalRelation => l.relation } snappyContextFunctions.postRelationCreation(relation, this) - var catalogTable = externalCatalog.getTable(resolvedName.database.get, resolvedName.table) - val primaryKeys = getPrimaryKeys(resolvedName.database.get, resolvedName.table) + if (!tableAlreadyExisted) { + updatePrimaryKeyDetails(resolvedIdentifier) + } + df + } + + private def updatePrimaryKeyDetails(resolvedIdentifier: TableIdentifier): Unit = { + val catalogTable = externalCatalog.getTable(resolvedIdentifier.database.get, + resolvedIdentifier.table) + val primaryKeys = getPrimaryKeys(resolvedIdentifier.database.get, resolvedIdentifier.table) if (primaryKeys.nonEmpty) { sessionCatalog.alterTable(catalogTable.copy(properties = catalogTable.properties + (s"primary_keys" -> primaryKeys.mkString(",")))) } - df } /** @@ -1472,9 +1485,10 @@ class SnappySession(_sc: SparkContext) extends SparkSession(_sc) { val rs = ps.executeQuery() if (rs.next()) { val keys = rs.getString(1) - if (keys != null && !keys.eq("")) + if (keys != null && !keys.eq("")) { // keys for table with c1, c2 as primary key looks like '+c1+c2' primaryKeys = keys.split("\\+").filter(!_.equals("")) + } } } catch { case sqle: SQLException => @@ -1655,7 +1669,8 @@ class SnappySession(_sc: SparkContext) extends SparkSession(_sc) { // and update it into the metastore. val metadata = sessionCatalog.getTableMetadata(tableIdent) - val primaryKeys = getPrimaryKeys(metadata.identifier.database.get, metadata.identifier.table) + val primaryKeys = getPrimaryKeys(metadata.identifier.database.get, + metadata.identifier.table) sessionCatalog.alterTable(metadata.copy( properties = metadata.properties + (s"altTxt_${System.currentTimeMillis()}" -> sql) + diff --git a/core/src/test/scala/org/apache/spark/sql/store/CatalogVersionTest.scala b/core/src/test/scala/org/apache/spark/sql/store/CatalogVersionTest.scala new file mode 100644 index 0000000000..f978376549 --- /dev/null +++ b/core/src/test/scala/org/apache/spark/sql/store/CatalogVersionTest.scala @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2017-2019 TIBCO Software Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you + * may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. See accompanying + * LICENSE file. + */ + +package org.apache.spark.sql.store + +import com.pivotal.gemfirexd.internal.engine.distributed.utils.GemFireXDUtils +import io.snappydata.SnappyFunSuite +import org.scalatest.BeforeAndAfter + +class CatalogVersionTest extends SnappyFunSuite with BeforeAndAfter { + val testTable = "catalog_version_test_table" + val testView = "catalog_version_test_view" + + before { + snc.sql(s"DROP TABLE IF EXISTS $testTable") + snc.sql(s"DROP VIEW IF EXISTS $testView") + } + + after { + snc.sql(s"DROP TABLE IF EXISTS $testTable") + snc.sql(s"DROP VIEW IF EXISTS $testView") + } + + test("catalog version update") { + val initialVersion = GemFireXDUtils.getGfxdAdvisor.getMyProfile.getCatalogSchemaVersion + snc.sql( + s"CREATE TABLE IF NOT EXISTS $testTable (ID INT, NAME STRING)") + val v1 = GemFireXDUtils.getGfxdAdvisor.getMyProfile.getCatalogSchemaVersion + assertResult(initialVersion + 1)(v1) + + snc.sql(s"CREATE TABLE IF NOT EXISTS $testTable (ID INT, NAME STRING)") + val v2 = GemFireXDUtils.getGfxdAdvisor.getMyProfile.getCatalogSchemaVersion + // Another execution of query should not update version as the table is already created + // earlier. + assertResult(initialVersion + 1)(v2) + + snc.sql(s"INSERT INTO $testTable VALUES(1,'NAME1')") + snc.sql(s"UPDATE $testTable SET NAME='XYZ' WHERE ID = 1") + snc.sql(s"DELETE FROM $testTable WHERE ID = 1") + val v3 = GemFireXDUtils.getGfxdAdvisor.getMyProfile.getCatalogSchemaVersion + // DML statement should not update catalog version + assertResult(initialVersion + 1)(v3) + + snc.sql(s"CREATE OR REPLACE VIEW $testView AS SELECT * FROM $testTable") + val v4 = GemFireXDUtils.getGfxdAdvisor.getMyProfile.getCatalogSchemaVersion + // View creation should increment catalog version + assertResult(initialVersion + 2)(v4) + + snc.sql(s"CREATE OR REPLACE VIEW $testView AS SELECT id FROM $testTable") + val v5 = GemFireXDUtils.getGfxdAdvisor.getMyProfile.getCatalogSchemaVersion + // Replacing the same view should increment catalog version + assertResult(initialVersion + 3)(v5) + + snc.sql(s"DROP VIEW $testView") + val v6 = GemFireXDUtils.getGfxdAdvisor.getMyProfile.getCatalogSchemaVersion + // Drop view should increment catalog version + assertResult(initialVersion + 4)(v6) + + snc.sql(s"DROP TABLE $testTable") + val v7 = GemFireXDUtils.getGfxdAdvisor.getMyProfile.getCatalogSchemaVersion + // Drop table should increment catalog version + assertResult(initialVersion + 5)(v7) + } + + test("catalog version update for 'create table if not exist ...' with primary keys") { + val initialVersion = GemFireXDUtils.getGfxdAdvisor.getMyProfile.getCatalogSchemaVersion + snc.sql(s"""CREATE TABLE IF NOT EXISTS $testTable + (ID INT, NAME STRING, PRIMARY KEY (ID)) USING ROW""") + val v1 = GemFireXDUtils.getGfxdAdvisor.getMyProfile.getCatalogSchemaVersion + // Version is incremented by one as when query contains primary keys, an extra alter table is + // performed after actually creating table. + // See org.apache.spark.sql.SnappySession.updatePrimaryKeyDetails + assertResult(initialVersion + 2)(v1) + + snc.sql(s"""CREATE TABLE IF NOT EXISTS $testTable + (ID INT, NAME STRING, PRIMARY KEY (ID)) USING ROW""") + val v2 = GemFireXDUtils.getGfxdAdvisor.getMyProfile.getCatalogSchemaVersion + // Another execution of query should not update version as the table is already created + // earlier. + assertResult(initialVersion + 2)(v2) + } +} From ebb67d184a6cea9555f33cffddd83034b40753b3 Mon Sep 17 00:00:00 2001 From: Trilok Khairnar <214651+cruizen@users.noreply.github.com> Date: Fri, 29 Nov 2019 15:25:16 +0530 Subject: [PATCH 029/101] Refactoring TPC-DS benchmark for SnappyData, Spark (#1469) Refactored the tpc-ds benchmark scripts, classes for small improvements --- .../snappy/tpcds/QueryExecutionJob.scala | 23 +++- .../benchmark/snappy/tpcds/SparkApp.scala | 65 +++++---- .../snappy/tpcds/TableCreationJob.scala | 123 +++++++++++++----- .../benchmark/snappy/tpch/QueryExecutor.scala | 23 ++-- .../snappy/tpch/TableCreationJob.scala | 1 + .../benchmark/snappy/dynamic/4_6_jobStatus.sh | 2 +- .../snappy/tpcds/1_cleanJavaOnMachines.sh | 2 +- tests/benchmark/snappy/tpcds/2_Setup.sh | 14 +- .../snappy/tpcds/3_createAndLoadTable.sh | 2 +- .../benchmark/snappy/tpcds/5_executeQuery.sh | 2 +- .../snappy/tpcds/PerfRun.conf.template | 38 +++--- .../snappy/tpcds/spark/1_stopMasterSlave.sh | 4 +- .../snappy/tpcds/spark/2_Setup_Table_Query.sh | 11 +- .../snappy/tpcds/spark/PerfRun.conf.template | 49 +++---- 14 files changed, 207 insertions(+), 152 deletions(-) diff --git a/cluster/src/test/scala/io/snappydata/benchmark/snappy/tpcds/QueryExecutionJob.scala b/cluster/src/test/scala/io/snappydata/benchmark/snappy/tpcds/QueryExecutionJob.scala index a77dc54723..d7ba64102a 100644 --- a/cluster/src/test/scala/io/snappydata/benchmark/snappy/tpcds/QueryExecutionJob.scala +++ b/cluster/src/test/scala/io/snappydata/benchmark/snappy/tpcds/QueryExecutionJob.scala @@ -41,8 +41,11 @@ object QueryExecutionJob extends SnappySQLJob with Logging { } val avgFileStream: FileOutputStream = new FileOutputStream( - new File(s"Snappy_Average.out")) + new File(s"Snappy_Average.csv")) val avgPrintStream: PrintStream = new PrintStream(avgFileStream) + var queryPrintStream: PrintStream = null + + avgPrintStream.println(s"Query,Iteration,ExecutionTime") queries.foreach { name => try { @@ -53,7 +56,7 @@ object QueryExecutionJob extends SnappySQLJob with Logging { val queryFileName = s"$name.out" val queryFileStream: FileOutputStream = new FileOutputStream(new File(queryFileName)) - val queryPrintStream: PrintStream = new PrintStream(queryFileStream) + queryPrintStream = new PrintStream(queryFileStream) var totalTime: Long = 0 @@ -89,6 +92,7 @@ object QueryExecutionJob extends SnappySQLJob with Logging { } val endTime = System.currentTimeMillis() val iterationTime = endTime - startTime + avgPrintStream.println(s"$name,$i,$iterationTime") // scalastyle:off println queryPrintStream.println(s"$iterationTime") @@ -103,15 +107,24 @@ object QueryExecutionJob extends SnappySQLJob with Logging { // println(s"${totalTime / runsForAverage}") println("-----------------------------------------------") queryPrintStream.println(s"${totalTime / runsForAverage}") - avgPrintStream.println(s"$name, executionTime = ${totalTime / runsForAverage}") + avgPrintStream.println(s"$name,mean,${totalTime / runsForAverage}") println("-----------------------------------------------") } catch { - case e: Exception => println(s"Failed $name") - logError("Exception in job", e) + case e: java.io.FileNotFoundException => + val message = s"Query file ${name} does not exist." + logError(message, e) + queryPrintStream.println(message) + case e: Exception => + val message = s"Query $name failed" + println(message) + logError(message) + logError("Exception in job: " + System.lineSeparator(), e) } } + + // cleanup avgPrintStream.close() avgFileStream.close() QueryExecutor.close diff --git a/cluster/src/test/scala/io/snappydata/benchmark/snappy/tpcds/SparkApp.scala b/cluster/src/test/scala/io/snappydata/benchmark/snappy/tpcds/SparkApp.scala index 8f6e2800de..b1e39710a7 100644 --- a/cluster/src/test/scala/io/snappydata/benchmark/snappy/tpcds/SparkApp.scala +++ b/cluster/src/test/scala/io/snappydata/benchmark/snappy/tpcds/SparkApp.scala @@ -33,7 +33,9 @@ object SparkApp { .getOrCreate() for(arg <- args){ + // scalastyle:off println println(arg) + // scalastyle:on println } val sparkSqlProps = args(0).split(",") @@ -44,10 +46,12 @@ object SparkApp { var isResultCollection = args(5).toBoolean var warmUp = args(6).toInt var runsForAverage = args(7).toInt + var cacheTables = args(8).toBoolean for (prop <- sparkSqlProps) { // scalastyle:off println println(prop) + // scalastyle:on println sc.sql(s"set $prop") } @@ -61,11 +65,6 @@ object SparkApp { println(s"****************queries : $queries") // scalastyle:on println - /*catalog_page", "catalog_returns", "customer", "customer_address", - "customer_demographics", "date_dim", "household_demographics", "inventory", "item", - "promotion", "store", "store_returns", "catalog_sales", "web_sales", "store_sales", - "web_returns", "web_site", "reason", "call_center", "warehouse", "ship_mode", "income_band", - "time_dim", "web_page"*/ val tables = Seq("call_center", "catalog_page", "date_dim", "household_demographics", "income_band", "promotion", "reason", "ship_mode", "store", "time_dim", @@ -74,14 +73,17 @@ object SparkApp { tables.map { tableName => sc.read.parquet(s"$dataLocation/$tableName").createOrReplaceTempView(tableName) - snc.cacheTable(tableName) + if (cacheTables) { + snc.cacheTable(tableName) + } val count = sc.table(tableName).count() tableName -> count // scalastyle:off println println("-----------------------------------------------") - println(s"Table Created...$tableName with rows $count") + println(s"Table Created...$tableName with $count rows") println("-----------------------------------------------") + // scalastyle:on println } /* @@ -98,39 +100,39 @@ object SparkApp { var partitionBy : String = "cr_order_number" var tableName : String = "catalog_returns" - createPartitionedTables(sc, dataLocation, partitionBy, tableName, buckets_ColumnTable) + createPartitionedTable(sc, dataLocation, partitionBy, tableName, buckets_ColumnTable, cacheTables) partitionBy = "cs_order_number" tableName = "catalog_sales" - createPartitionedTables(sc, dataLocation, partitionBy, tableName, buckets_ColumnTable) + createPartitionedTable(sc, dataLocation, partitionBy, tableName, buckets_ColumnTable, cacheTables) partitionBy = "c_customer_sk" tableName = "customer" - createPartitionedTables(sc, dataLocation, partitionBy, tableName, buckets_ColumnTable) + createPartitionedTable(sc, dataLocation, partitionBy, tableName, buckets_ColumnTable, cacheTables) partitionBy = "ca_address_sk" tableName = "customer_address" - createPartitionedTables(sc, dataLocation, partitionBy, tableName, buckets_ColumnTable) + createPartitionedTable(sc, dataLocation, partitionBy, tableName, buckets_ColumnTable, cacheTables) partitionBy = "inv_item_sk" tableName = "inventory" - createPartitionedTables(sc, dataLocation, partitionBy, tableName, buckets_ColumnTable) + createPartitionedTable(sc, dataLocation, partitionBy, tableName, buckets_ColumnTable, cacheTables) partitionBy = "sr_item_sk" tableName = "store_returns" - createPartitionedTables(sc, dataLocation, partitionBy, tableName, buckets_ColumnTable) + createPartitionedTable(sc, dataLocation, partitionBy, tableName, buckets_ColumnTable, cacheTables) partitionBy = "ss_item_sk" tableName = "store_sales" - createPartitionedTables(sc, dataLocation, partitionBy, tableName, buckets_ColumnTable) + createPartitionedTable(sc, dataLocation, partitionBy, tableName, buckets_ColumnTable, cacheTables) partitionBy = "wr_order_number" tableName = "web_returns" - createPartitionedTables(sc, dataLocation, partitionBy, tableName, buckets_ColumnTable) + createPartitionedTable(sc, dataLocation, partitionBy, tableName, buckets_ColumnTable, cacheTables) - partitionBy = "ws_order_number" + partitionBy = "ws_order_number" tableName = "web_sales" - createPartitionedTables(sc, dataLocation, partitionBy, tableName, buckets_ColumnTable) + createPartitionedTable(sc, dataLocation, partitionBy, tableName, buckets_ColumnTable, cacheTables) var avgFileStream: FileOutputStream = new FileOutputStream( @@ -150,7 +152,6 @@ object SparkApp { println(s"Running Query $name now.") for (i <- 1 to (warmUp + runsForAverage)) { - // queryPrintStream.println(queryToBeExecuted) val startTime = System.currentTimeMillis() var cnts: Array[Row] = null if (i == 1) { @@ -165,7 +166,6 @@ object SparkApp { val endTime = System.currentTimeMillis() val iterationTime = endTime - startTime - // scalastyle:off println println(s"iterationTime = $iterationTime") if (i > warmUp) { @@ -174,45 +174,38 @@ object SparkApp { cnts = null } - // scalastyle:off println - //println(s"${totalTime / runsForAverage}") + // println(s"${totalTime / runsForAverage}") println("-----------------------------------------------") avgPrintStream.println(s"$name, executionTime = ${totalTime / runsForAverage}") println("-----------------------------------------------") } catch { - case e: Exception => println(s"Failed $name " + e.printStackTrace()) + case e: Exception => println(s"Failed query $name " + e.printStackTrace()) } } -// try { -// Thread.sleep(Long.MaxValue) -// } -// catch { -// case _ => -// } - //TPCDSQuerySnappyBenchmark.snappy = snSession - //TPCDSQuerySnappyBenchmark.execute(dataLocation, queries, true, queryPath) } - def createPartitionedTables(sc: SparkSession, dataLocation: String, - partitionBy: String , tableName: String, buckets: Int): Unit = { + def createPartitionedTable(sc: SparkSession, dataLocation: String, + partitionBy: String, tableName: String, buckets: Int, + cacheTables: Boolean = true): Unit = { val df = sc.sqlContext.read.parquet(s"$dataLocation/$tableName") df.createOrReplaceTempView(tableName) df.repartition(buckets, df(partitionBy)).createOrReplaceTempView(tableName) df.createOrReplaceTempView(tableName) - sc.sqlContext.cacheTable(tableName) + if (cacheTables) { + sc.sqlContext.cacheTable(tableName) + } // tableName -> sc.table(tableName).count() val count = sc.table(tableName).count() // scalastyle:off println println("-----------------------------------------------") - println(s"Table Created...$tableName with row $count") + println(s"Table $tableName created with $count rows") println("-----------------------------------------------") + // scalastyle:on println } - //TPCDSQuerySnappyBenchmark.spark = sc - //TPCDSQuerySnappyBenchmark.execute(dataLocation, queries, false, queryPath) } diff --git a/cluster/src/test/scala/io/snappydata/benchmark/snappy/tpcds/TableCreationJob.scala b/cluster/src/test/scala/io/snappydata/benchmark/snappy/tpcds/TableCreationJob.scala index 3c84e518a8..bceb0a58cb 100644 --- a/cluster/src/test/scala/io/snappydata/benchmark/snappy/tpcds/TableCreationJob.scala +++ b/cluster/src/test/scala/io/snappydata/benchmark/snappy/tpcds/TableCreationJob.scala @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2017-2019 TIBCO Software Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you + * may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. See accompanying + * LICENSE file. + */ package io.snappydata.benchmark.snappy.tpcds import java.io.{File, FileOutputStream, PrintStream} @@ -19,8 +35,9 @@ object TableCreationJob extends SnappySQLJob{ snc.sparkContext.hadoopConfiguration.set("fs.s3a.connection.maximum", "1000"); val isSnappy = true - val loadPerfFileStream: FileOutputStream = new FileOutputStream(new File("Snappy_LoadPerf.out")) + val loadPerfFileStream: FileOutputStream = new FileOutputStream(new File("Snappy_LoadPerf.csv")) val loadPerfPrintStream: PrintStream = new PrintStream(loadPerfFileStream) + loadPerfPrintStream.println("Table,RowCount,CreationTimeInMilliSeconds") for (prop <- sqlSparkProperties) { snc.sql(s"set $prop") @@ -28,85 +45,125 @@ object TableCreationJob extends SnappySQLJob{ val tables = Seq("call_center", "catalog_page", "date_dim", "household_demographics", "income_band", "promotion", "reason", "ship_mode", "store", "time_dim", - "warehouse", "web_page" , "web_site", "item", "customer_demographics") + "warehouse", "web_page" , "web_site") + // item (~100k rows, 8 buckets) & customer_demographics (2 Million rows) are now column tables tables.map { tableName => - //println(s"Table Creation Started...$tableName") + println(s"Table Creation Started...$tableName") val df = snSession.read.parquet(s"$dataLocation/$tableName") + snSession.dropTable(tableName, ifExists = true) + val startTime = System.currentTimeMillis() snSession.createTable(tableName, "row", new StructType(df.schema.map(_.copy(nullable = true)).toArray), Map[String, String] ()) df.write.insertInto(tableName) - val cnt = df.collect().length; + val endTime = System.currentTimeMillis() + //val cnt = df.collect().length; // avoid collect.length since it's slower than df.count + val cnt = df.count(); // scalastyle:off println + // Get the number of rows in the table created by querying + val rowCount = snSession.sql(s"SELECT COUNT(*) FROM $tableName").first().get(0) println("-----------------------------------------------") - println(s"Table Created...$tableName with rows $cnt") - + println(s"Table $tableName with $rowCount rows created from " + + s"file $dataLocation/$tableName with $cnt rows") println("-----------------------------------------------") + loadPerfPrintStream.println(s"$tableName,$rowCount,${endTime - startTime}") } + var partitionBy : String = "" - var props = Map(("PARTITION_BY" -> "cr_order_number"), ("BUCKETS" -> buckets_ColumnTable)) + // partitionBy = "cr_order_number" + partitionBy = "cr_returned_date_sk" + var props = Map(("PARTITION_BY" -> partitionBy), ("BUCKETS" -> buckets_ColumnTable)) var tableName = "catalog_returns" - createColumnPartitionedTables(snSession, props, tableName) + createColumnPartitionedTable(snSession, props, tableName, loadPerfPrintStream) - props = Map(("PARTITION_BY" -> "cs_order_number"), ("BUCKETS" -> buckets_ColumnTable), + // partitionBy = "cs_order_number" + partitionBy = "cs_sold_date_sk" + props = Map(("PARTITION_BY" -> partitionBy), ("BUCKETS" -> buckets_ColumnTable), ("COLOCATE_WITH" -> "CATALOG_RETURNS")) tableName = "catalog_sales" - createColumnPartitionedTables(snSession, props, tableName) + createColumnPartitionedTable(snSession, props, tableName, loadPerfPrintStream) - props = Map(("PARTITION_BY" -> "wr_order_number"), ("BUCKETS" -> buckets_ColumnTable), + // partitionBy = "wr_order_number" + partitionBy = "wr_returned_date_sk" + props = Map(("PARTITION_BY" -> partitionBy), ("BUCKETS" -> buckets_ColumnTable), ("COLOCATE_WITH" -> "CATALOG_SALES")) tableName = "web_returns" - createColumnPartitionedTables(snSession, props, tableName) + createColumnPartitionedTable(snSession, props, tableName, loadPerfPrintStream) - props = Map(("PARTITION_BY" -> "ws_order_number"), ("BUCKETS" -> buckets_ColumnTable), + // partitionBy = "ws_order_number" + partitionBy = "ws_sold_date_sk" + props = Map(("PARTITION_BY" -> partitionBy), ("BUCKETS" -> buckets_ColumnTable), ("COLOCATE_WITH" -> "WEB_RETURNS")) tableName = "web_sales" - createColumnPartitionedTables(snSession, props, tableName) - + createColumnPartitionedTable(snSession, props, tableName, loadPerfPrintStream) - props = Map(("PARTITION_BY" -> "inv_item_sk"), ("BUCKETS" -> buckets_ColumnTable)) + partitionBy = "inv_item_sk" + props = Map(("PARTITION_BY" -> partitionBy), ("BUCKETS" -> buckets_ColumnTable)) tableName = "inventory" - createColumnPartitionedTables(snSession, props, tableName) + createColumnPartitionedTable(snSession, props, tableName, loadPerfPrintStream) - props = Map(("PARTITION_BY" -> "sr_item_sk"), ("BUCKETS" -> buckets_ColumnTable), + partitionBy = "sr_item_sk" + props = Map(("PARTITION_BY" -> partitionBy), ("BUCKETS" -> buckets_ColumnTable), ("COLOCATE_WITH" -> "INVENTORY")) tableName = "store_returns" - createColumnPartitionedTables(snSession, props, tableName) + createColumnPartitionedTable(snSession, props, tableName, loadPerfPrintStream) - props = Map(("PARTITION_BY" -> "ss_item_sk"), ("BUCKETS" -> buckets_ColumnTable), + partitionBy = "ss_item_sk" + props = Map(("PARTITION_BY" -> partitionBy), ("BUCKETS" -> buckets_ColumnTable), ("COLOCATE_WITH" -> "STORE_RETURNS")) tableName = "store_sales" - createColumnPartitionedTables(snSession, props, tableName) - + createColumnPartitionedTable(snSession, props, tableName, loadPerfPrintStream) - props = Map(("PARTITION_BY" -> "c_customer_sk"), ("BUCKETS" -> buckets_ColumnTable)) + partitionBy = "c_customer_sk" + props = Map(("PARTITION_BY" -> partitionBy), ("BUCKETS" -> buckets_ColumnTable)) tableName = "customer" - createColumnPartitionedTables(snSession, props, tableName) + createColumnPartitionedTable(snSession, props, tableName, loadPerfPrintStream) - props = Map(("PARTITION_BY" -> "ca_address_sk"), ("BUCKETS" -> buckets_ColumnTable)) + partitionBy = "ca_address_sk" + props = Map(("PARTITION_BY" -> partitionBy), ("BUCKETS" -> buckets_ColumnTable)) tableName = "customer_address" - createColumnPartitionedTables(snSession, props, tableName) + createColumnPartitionedTable(snSession, props, tableName, loadPerfPrintStream) + + partitionBy = "cd_demo_sk" + props = Map(("PARTITION_BY" -> partitionBy), ("BUCKETS" -> buckets_ColumnTable)) + tableName = "customer_demographics" + createColumnPartitionedTable(snSession, props, tableName, loadPerfPrintStream) + + partitionBy = "i_item_sk" + props = Map(("PARTITION_BY" -> partitionBy), ("BUCKETS" -> "8")) + tableName = "item" + createColumnPartitionedTable(snSession, props, tableName, loadPerfPrintStream) - val avgFileStream: FileOutputStream = new FileOutputStream( - new File(s"Snappy_Average.out")) - val avgPrintStream: PrintStream = new PrintStream(avgFileStream) + // cleanup + loadPerfPrintStream.flush() + loadPerfFileStream.flush() + loadPerfPrintStream.close() + loadPerfFileStream.close() } - def createColumnPartitionedTables(snappy: SnappySession, - props: Map[String,String] , tableName: String): Unit = { + def createColumnPartitionedTable(snappy: SnappySession, props: Map[String, String], + tableName: String, loadPerfPrintStream: PrintStream): Unit = { val df = snappy.read.parquet(s"$dataLocation/$tableName") + snappy.dropTable(tableName, ifExists = true) + val startTime = System.currentTimeMillis() snappy.createTable(tableName, "column", new StructType(df.schema.map(_.copy(nullable = false)).toArray), props) df.write.insertInto(tableName) - val cnt = df.collect().length + val endTime = System.currentTimeMillis() + // val cnt = df.collect().length + // collect().length takes a very long time to run and may cause memory pressure + val cnt = df.count() // scalastyle:off println + val rowCount = snappy.sql(s"SELECT COUNT(*) FROM $tableName").first().get(0) println("-----------------------------------------------") - println(s"Table Created...$tableName with rows $cnt") + println(s"Table $tableName with $rowCount rows created from " + + s"file $dataLocation/$tableName with $cnt rows") println("-----------------------------------------------") + loadPerfPrintStream.println(s"$tableName,$rowCount,${endTime - startTime}") } override def isValidJob(snSession: SnappySession, config: Config): SnappyJobValidation = { diff --git a/cluster/src/test/scala/io/snappydata/benchmark/snappy/tpch/QueryExecutor.scala b/cluster/src/test/scala/io/snappydata/benchmark/snappy/tpch/QueryExecutor.scala index d9315befaf..c0f183a420 100644 --- a/cluster/src/test/scala/io/snappydata/benchmark/snappy/tpch/QueryExecutor.scala +++ b/cluster/src/test/scala/io/snappydata/benchmark/snappy/tpch/QueryExecutor.scala @@ -24,9 +24,6 @@ import io.snappydata.benchmark.TPCH_Queries import org.apache.spark.sql.{DataFrame, Row, SQLContext} -/** - * Created by kishor on 27/10/15. - */ object QueryExecutor { var planFileStream: FileOutputStream = _ @@ -37,7 +34,7 @@ object QueryExecutor { planFileStream.close() } - def setRandomSeed(randomSeed : Integer): Unit ={ + def setRandomSeed(randomSeed : Integer): Unit = { TPCH_Queries.setRandomSeed(randomSeed) } @@ -50,7 +47,7 @@ object QueryExecutor { var rs: ResultSet = null try { // scalastyle:off println - println(s"Started executing $queryNumber") + println(s"Started executing query $queryNumber") if (isResultCollection) { rs = queryExecution(queryNumber, stmt) // queryPrintStream.println(s"$resultFormat") @@ -65,8 +62,8 @@ object QueryExecutor { } queryPrintStream.println() } - println(s"Number of results : $count") - println(s"$queryNumber Result collected in file $queryNumber.out") + println(s"Number of rows in query $queryNumber result : $count") + println(s"Query $queryNumber Result collected in file $queryNumber.out") if (queryNumber.equals("13")) { stmt.execute("drop view ViewQ13") } @@ -125,7 +122,8 @@ object QueryExecutor { else s"${threadNumber}_QueryPlans_Spark.out" val queryResultsFileName = if (isSnappy) s"${threadNumber}_Snappy_Q${queryNumber}_Results.out" else s"${threadNumber}_Spark_Q${queryNumber}_Results.out" - val queryStatisticsFileName = if (isSnappy) s"${threadNumber}_Snappy_Q${queryNumber}_Timings.csv" + val queryStatisticsFileName = + if (isSnappy) s"${threadNumber}_Snappy_Q${queryNumber}_Timings.csv" else s"${threadNumber}_Spark_Q${queryNumber}_Timings.csv" if (planFileStream == null && planPrintStream == null) { @@ -133,7 +131,8 @@ object QueryExecutor { planPrintStream = new PrintStream(planFileStream) } - val queryStatisticsFileStream: FileOutputStream = new FileOutputStream(new File(queryStatisticsFileName)) + val queryStatisticsFileStream: FileOutputStream = + new FileOutputStream(new File(queryStatisticsFileName)) val queryStatisticsPrintStream: PrintStream = new PrintStream(queryStatisticsFileStream) queryStatisticsPrintStream.println(s"Iteration,ResponseTime") // scalastyle:off println @@ -141,12 +140,14 @@ object QueryExecutor { println(s"Started executing $queryNumber") if (isResultCollection) { - val queryResultsFileStream: FileOutputStream = new FileOutputStream(new File(queryResultsFileName)) + val queryResultsFileStream: FileOutputStream = + new FileOutputStream(new File(queryResultsFileName)) val queryResultsPrintStream: PrintStream = new PrintStream(queryResultsFileStream) try { var queryToBeExecuted = TPCH_Queries.getQuery(queryNumber, isDynamic, isSnappy = true) - val (resultSet, _) = queryExecution(queryNumber, queryToBeExecuted, sqlContext, genPlan = true) + val (resultSet, _) = + queryExecution(queryNumber, queryToBeExecuted, sqlContext, genPlan = true) println(s"$queryNumber : ${resultSet.length}") for (row <- resultSet) { diff --git a/cluster/src/test/scala/io/snappydata/benchmark/snappy/tpch/TableCreationJob.scala b/cluster/src/test/scala/io/snappydata/benchmark/snappy/tpch/TableCreationJob.scala index 61064963ed..156b4793a2 100644 --- a/cluster/src/test/scala/io/snappydata/benchmark/snappy/tpch/TableCreationJob.scala +++ b/cluster/src/test/scala/io/snappydata/benchmark/snappy/tpch/TableCreationJob.scala @@ -63,6 +63,7 @@ object TableCreationJob extends SnappySQLJob { snc.dropTable("LINEITEM", ifExists = true) snc.dropTable("ORDERS", ifExists = true) + // cacheTables = false for SnappyData since SnappyData doesn't use Spark caching TPCHReplicatedTable.createPopulateRegionTable(usingOptionString, snc, tpchDataPath, isSnappy, loadPerfPrintStream, trace = false, cacheTables = false) TPCHReplicatedTable.createPopulateNationTable(usingOptionString, snc, tpchDataPath, isSnappy, diff --git a/tests/benchmark/snappy/dynamic/4_6_jobStatus.sh b/tests/benchmark/snappy/dynamic/4_6_jobStatus.sh index 28c7b0894f..f139c74e0d 100755 --- a/tests/benchmark/snappy/dynamic/4_6_jobStatus.sh +++ b/tests/benchmark/snappy/dynamic/4_6_jobStatus.sh @@ -1,4 +1,4 @@ #!/usr/bin/env bash source PerfRun.conf -bash $SnappyData/bin/snappy-job.sh --lead $2:8090 status --job-id $1 +bash $SnappyData/bin/snappy-job.sh --lead $leads:8090 status --job-id $1 diff --git a/tests/benchmark/snappy/tpcds/1_cleanJavaOnMachines.sh b/tests/benchmark/snappy/tpcds/1_cleanJavaOnMachines.sh index 77d8635636..0c289f0bad 100755 --- a/tests/benchmark/snappy/tpcds/1_cleanJavaOnMachines.sh +++ b/tests/benchmark/snappy/tpcds/1_cleanJavaOnMachines.sh @@ -2,7 +2,7 @@ source PerfRun.conf echo "*****************Stop locator, server, lead***********************" -sh $SnappyData/sbin/snappy-stop-all.sh +$SnappyData/sbin/snappy-stop-all.sh rm -rf $SnappyData/work/* rm -rf $SnappyData/conf/leads diff --git a/tests/benchmark/snappy/tpcds/2_Setup.sh b/tests/benchmark/snappy/tpcds/2_Setup.sh index a30110a5db..de3da1d0a6 100755 --- a/tests/benchmark/snappy/tpcds/2_Setup.sh +++ b/tests/benchmark/snappy/tpcds/2_Setup.sh @@ -35,16 +35,16 @@ for element in "${servers[@]}"; echo "******************Created conf/servers******************" -#sh $SnappyData/sbin/snappy-start-all.sh start -classpath=$TPCHJar +#sh $SnappyData/sbin/snappy-start-all.sh start -classpath=$appJar echo "******************start locators******************" -#sh $SnappyData/sbin/snappy-locators.sh start -classpath=$TPCHJar -sh $SnappyData/sbin/snappy-locators.sh start +#sh $SnappyData/sbin/snappy-locators.sh start -classpath=$appJar +$SnappyData/sbin/snappy-locators.sh start echo "******************start servers******************" -sh $SnappyData/sbin/snappy-servers.sh -bg start -#sh $SnappyData/sbin/snappy-servers.sh start -classpath=$TPCHJar +$SnappyData/sbin/snappy-servers.sh -bg start +#sh $SnappyData/sbin/snappy-servers.sh start -classpath=$appJar echo "******************start leads******************" -sh $SnappyData/sbin/snappy-leads.sh start -#sh $SnappyData/sbin/snappy-leads.sh start -classpath=$TPCHJar +$SnappyData/sbin/snappy-leads.sh start +#sh $SnappyData/sbin/snappy-leads.sh start -classpath=$appJar diff --git a/tests/benchmark/snappy/tpcds/3_createAndLoadTable.sh b/tests/benchmark/snappy/tpcds/3_createAndLoadTable.sh index 79356c61f7..04e5789874 100755 --- a/tests/benchmark/snappy/tpcds/3_createAndLoadTable.sh +++ b/tests/benchmark/snappy/tpcds/3_createAndLoadTable.sh @@ -6,4 +6,4 @@ source PerfRun.conf cp PerfRun.conf $leadDir echo "******************start Creating Table******************" -. $SnappyData/bin/snappy-job.sh submit --lead $leads:8090 --app-name TableCreation --class io.snappydata.benchmark.snappy.tpcds.TableCreationJob --app-jar $appJar --conf sparkSqlProps=$sparkSqlProps --conf dataDir=$dataDir --conf Buckets_ColumnTable=$buckets_ColumnTable \ No newline at end of file +. $SnappyData/bin/snappy-job.sh submit --lead $leads:8090 --app-name TableCreation --class io.snappydata.benchmark.snappy.tpcds.TableCreationJob --app-jar $appJar --conf sparkSqlProps=$sparkSqlProps --conf dataDir=$dataDir --conf Buckets_ColumnTable=$buckets_ColumnTable diff --git a/tests/benchmark/snappy/tpcds/5_executeQuery.sh b/tests/benchmark/snappy/tpcds/5_executeQuery.sh index 27fb58778b..1b09d238cf 100755 --- a/tests/benchmark/snappy/tpcds/5_executeQuery.sh +++ b/tests/benchmark/snappy/tpcds/5_executeQuery.sh @@ -14,7 +14,7 @@ echo "******************start Executing Query******************" --class io.snappydata.benchmark.snappy.tpcds.QueryExecutionJob \ --app-jar $appJar \ --conf queries=$queries \ ---conf sparkSqlProps=sparkSqlProps \ +--conf sparkSqlProps=$sparkSqlProps \ --conf resultCollection=$ResultCollection \ --conf warmUpIterations=$WarmupRuns \ --conf actualRuns=$AverageRuns \ diff --git a/tests/benchmark/snappy/tpcds/PerfRun.conf.template b/tests/benchmark/snappy/tpcds/PerfRun.conf.template index 991c644818..41e35277a5 100644 --- a/tests/benchmark/snappy/tpcds/PerfRun.conf.template +++ b/tests/benchmark/snappy/tpcds/PerfRun.conf.template @@ -1,24 +1,23 @@ #Do not change the way of queries, sparkProperties, sparkSqlProperties. Just change the values inside strings #queries to be run -#queries="\"q1,q2,q3,q4,q5,q6,q7,q8,q9,q10\"" -#queries=10 -queries="\"q1,q2,q3,q4,q5,q6,q7,q8,q9,q10,q11,q12,q13,q14,q15,q16,q17,q18,q19,q20,q21,q22,q23,q24,q25,q26,q27,q28,q29,q30,q31,q32,q33,q34,q35,q36,q37,q38,q39,q40,q41,q42,q43,q44,q45,q46,q47,q48,q49,q50,q51,q52,q53,q54,q55,q56,q57,q58,q59,q60,q61,q62,q63,q64,q65,q66,q67,q68,q69,q70,q71,q72,q73,q74,q75,q76,q77,q78,q79,q80,q81,q82,q83,q84,q85,q86,q87,q88,q89,q90,q91,q92,q93,q94,q95,q96,q97,q98,q99\"" - +queries="q1,q2,q3,q4,q5,q6,q7,q8,q9,q10,q11,q12,q13,q14a,q14b,q15,q16,q17,q18,q19,q20,q21,q22,q23a,q23b,q24a,q24b,q25,q26,q27,q28,q29,q30,q31,q32,q33,q34,q35,q36,q37,q38,q39a,q39b,q40,q41,q42,q43,q44,q45,q46,q47,q48,q49,q50,q51,q52,q53,q54,q55,q56,q57,q58,q59,q60,q61,q62,q63,q64,q65,q66,q67,q68,q69,q70,q71,q72,q73,q74,q75,q76,q77,q78,q79,q80,q81,q82,q83,q84,q85,q86,q87,q88,q89,q90,q91,q92,q93,q94,q95,q96,q97,q98,q99" #spark Properties spefied in lead #spark-executor-cores has nothing to do with CPU cores available. #sparkProperties="-J-Xmx2g -spark.network.timeout=300s -spark.driver.maxResultSize=2g -spark.shuffle.sort.bypassMergeThreshold=28" -sparkProperties="-heap-size=4g -memory-size=4g -conserve-sockets=false" +# the lead uses heap, not off-heap memory. No need to specify -memory-size +sparkProperties="-heap-size=4g -spark.driver.maxResultSize=2g" #Spark Sql properties are specified while executing query #spark.sql.shuffle.partitions=${shufflePartitions},spark.sql.inMemoryColumnarStorage.compressed=${inMemoryColumnarStorageCompressed} #spark.sql.inMemoryColumnarStorage.compressed=false -sparkSqlProps="\"\"" +# enable cross join in sql props to allow running some queries that fail otherwise in Spark, SnappyData +sparkSqlProps="\"spark.sql.crossJoin.enabled=true\"" #location of checkout -SnappyData=/home/kishor/SNAPPY/CHECKOUT/snappydata/build-artifacts/scala-2.11/snappy -#SnappyData=/home/kishor/SNAPPY/CHECKOUT/snappydata-0.7-bin +SnappyData=$HOME/SNAPPY/CHECKOUT/snappydata/build-artifacts/scala-2.11/snappy +#SnappyData=$HOME/SNAPPY/CHECKOUT/snappydata-0.7-bin buckets_ColumnTable=5 @@ -28,33 +27,34 @@ WarmupRuns=1 AverageRuns=1 #Machine Setup -locator=localhost -leads=localhost -servers=(localhost) -#servers=(localhost) +locator=$HOSTNAME +leads=$HOSTNAME +servers=($HOSTNAME) #Log Directories -locatorDir=/home/kishor/SNAPPY/OUTPUT/TPCDS/locator -leadDir=/home/kishor/SNAPPY/OUTPUT/TPCDS/lead -serverDir=/home/kishor/SNAPPY/OUTPUT/TPCDS/server +locatorDir=$HOME/SNAPPY/OUTPUT/TPCDS/locator +leadDir=$HOME/SNAPPY/OUTPUT/TPCDS/lead +serverDir=$HOME/SNAPPY/OUTPUT/TPCDS/server #Locator Properties -locatorProperties="-conserve-sockets=false -J-Xloggc:gc.log -J-XX:+PrintGCDetails -J-XX:+PrintGCDateStamps -J-XX:+PrintGCTimeStamps -J-XX:+PrintHeapAtGC" +# Some disgnostic options here for reference that do not need to be specified as defaults +#locatorProperties="-conserve-sockets=false -J-Xloggc:gc.log -J-XX:+PrintGCDetails -J-XX:+PrintGCDateStamps -J-XX:+PrintGCTimeStamps -J-XX:+PrintHeapAtGC" +locatorProperties="" #Server properties serverMemory="-heap-size=2g -memory-size=4g -conserve-sockets=false-J-XX:NewRatio=9 -J-Xloggc:gc.log -J-XX:+PrintGCDetails -J-XX:+PrintGCDateStamps -J-XX:+PrintGCTimeStamps -J-XX:+PrintHeapAtGC" # location of jar which has TPCH related class files -appJar=/home/kishor/SNAPPY/CHECKOUT/snappydata/cluster/build-artifacts/scala-2.11/libs/snappydata-cluster_2.11-1.0.0-tests.jar +appJar=$HOME/SNAPPY/CHECKOUT/snappydata/cluster/build-artifacts/scala-2.11/libs/snappydata-cluster_2.11-1.1.1-tests.jar #Size of the TPCH data. Do not chage format #dataSize=1GB_Stages #dataSize=1GB #Location of the TPCH Data. Make sure directory name is same as the dataSize specified above -dataDir=/home/kishor/SNAPPY/DATA/TPCDS/data +dataDir=$HOME/SNAPPY/DATA/TPCDS/data #QueryPath -queryPath=/home/kishor/SNAPPY/CHECKOUT/snappydata/spark/sql/core/src/test/resources/tpcds +queryPath=$HOME/SNAPPY/CHECKOUT/snappydata/spark/sql/core/src/test/resources/tpcds diff --git a/tests/benchmark/snappy/tpcds/spark/1_stopMasterSlave.sh b/tests/benchmark/snappy/tpcds/spark/1_stopMasterSlave.sh index b080ca6a7f..5c65b29e30 100755 --- a/tests/benchmark/snappy/tpcds/spark/1_stopMasterSlave.sh +++ b/tests/benchmark/snappy/tpcds/spark/1_stopMasterSlave.sh @@ -2,9 +2,9 @@ source PerfRun.conf #top master and slaves from master machines -ssh $master bash $SnappyData/sbin/stop-all.sh +ssh $master bash $sparkHome/sbin/stop-all.sh -rm -rf $SnappyData/conf/slaves +rm -rf $sparkHome/conf/slaves #echo "*****************kill java on lead**********************" #ssh $client killall -9 java diff --git a/tests/benchmark/snappy/tpcds/spark/2_Setup_Table_Query.sh b/tests/benchmark/snappy/tpcds/spark/2_Setup_Table_Query.sh index d058403b0e..61fcc204a3 100755 --- a/tests/benchmark/snappy/tpcds/spark/2_Setup_Table_Query.sh +++ b/tests/benchmark/snappy/tpcds/spark/2_Setup_Table_Query.sh @@ -5,18 +5,15 @@ source PerfRun.conf # Create slaves configuration files for element in "${slaves[@]}"; do - echo $element >> $SnappyData/conf/slaves + echo $element >> $sparkHome/conf/slaves done echo "******************Created conf/slaves******************" #Start master and slaves from master machines -ssh $master sh $SnappyData/sbin/start-all.sh +ssh $master bash $sparkHome/sbin/start-all.sh #Execute Spark App -bash $SnappyData/bin/spark-submit \ +bash $sparkHome/bin/spark-submit \ --master spark://$master:7077 \ --class io.snappydata.benchmark.snappy.tpcds.SparkApp \ -$appJar $sparkSqlProperties $dataDir $queries $queryPath $buckets_ColumnTable $ResultCollection $WarmupRuns $AverageRuns - - - +$appJar $sparkSqlProperties $dataDir $queries $queryPath $buckets_ColumnTable $ResultCollection $WarmupRuns $AverageRuns $cacheTables diff --git a/tests/benchmark/snappy/tpcds/spark/PerfRun.conf.template b/tests/benchmark/snappy/tpcds/spark/PerfRun.conf.template index d95cf0acc6..01e6009b52 100755 --- a/tests/benchmark/snappy/tpcds/spark/PerfRun.conf.template +++ b/tests/benchmark/snappy/tpcds/spark/PerfRun.conf.template @@ -1,10 +1,7 @@ #Do not change the way of queries, sparkProperties, sparkSqlProperties. Just change the values inside strings #queries to be run -queries="1-2-3-4-5-6-7-8-9-10-11-12-13-14-15-16-17-18-19-20-22-21" -#queries=10 -#queries="\"1-3-14\"" - +queries="q1,q2,q3,q4,q5,q6,q7,q8,q9,q10,q11,q12,q13,q14a,q14b,q15,q16,q17,q18,q19,q20,q21,q22,q23a,q23b,q24a,q24b,q25,q26,q27,q28,q29,q30,q31,q32,q33,q34,q35,q36,q37,q38,q39a,q39b,q40,q41,q42,q43,q44,q45,q46,q47,q48,q49,q50,q51,q52,q53,q54,q55,q56,q57,q58,q59,q60,q61,q62,q63,q64,q65,q66,q67,q68,q69,q70,q71,q72,q73,q74,q75,q76,q77,q78,q79,q80,q81,q82,q83,q84,q85,q86,q87,q88,q89,q90,q91,q92,q93,q94,q95,q96,q97,q98,q99" #spark Properties spefied in lead #spark-executor-cores has nothing to do with CPU cores available. @@ -14,27 +11,18 @@ sparkProperties="--driver-memory 2g --conf spark.executor.memory=3g" #Spark Sql properties are specified while executing query #spark.sql.shuffle.partitions=${shufflePartitions},spark.sql.inMemoryColumnarStorage.compressed=${inMemoryColumnarStorageCompressed} #spark.sql.inMemoryColumnarStorage.compressed=false -sparkSqlProperties="\"\"" +sparkSqlProperties="" #location of checkout -#SnappyData=/home/kishor/SNAPPY/CHECKOUT/snappydata/build-artifacts/scala-2.11/snappy -SnappyData=/home/kishor/SNAPPY/CHECKOUT/spark-2.1.1-bin-hadoop2.7 -#SnappyData=/home/kishor/SNAPPY/CHECKOUT/snappydata-0.7-bin +#SnappyData=$HOME/SNAPPY/CHECKOUT/snappydata/build-artifacts/scala-2.11/snappy +sparkHome=$APACHE_SPARK_HOME/spark-2.1.1-bin-hadoop2.7 +#SnappyData=$HOME/SNAPPY/CHECKOUT/snappydata-1.1.2-bin #Whether to repartition dataframe rePartition=true -#number of buckets for order and lineitem tables -buckets_Order_Lineitem=113 - -#number of buckets for Customer, Part and PartSupplier tables -buckets_Cust_Part_PartSupp=113 - -#Are Nation, Region, Supplier tables column tables? -IsSupplierColumnTable=false - -#number of buckets for Nation, Region, Supplier -buckets_Supplier=113 +#number of buckets for column tables +buckets_ColumnTable=128 #Loading from parquet or csv file Parquet=false @@ -44,9 +32,9 @@ Parquet=false NumberOfLoadStages=10 #Machine Setup -master=pnq-kbachhav -slaves=(pnq-kbachhav) -client=pnq-kbachhav +master=$HOSTNAME +slaves=($HOSTNAME) +client=$HOSTNAME #represent whether query should use dynamic paramters or static IsDynamic=true @@ -59,16 +47,21 @@ WarmupRuns=2 #Actual runs whose average will be taken and repordted as performance AverageRuns=3 -# location of jar which has TPCH related class files -TPCHJar=/home/kishor/SNAPPY/CHECKOUT/snappydata/cluster/build-artifacts/scala-2.11/libs/snappydata-cluster_2.11-0.9-tests.jar +# location of the jar that contains TPC-DS, TPC-H benchmark related class files +appJar=$HOME/SNAPPY/CHECKOUT/snappydata/cluster/build-artifacts/scala-2.11/libs/snappydata-cluster_2.11-1.1.1.-tests.jar -#Size of the TPCH data. Do not chage format +#Size of the TPC-DS data. Do not chage format dataSize=1GB_Stages #dataSize=1GB -#Location of the TPCH Data. Make sure directory name is same as the dataSize specified above -dataDir=/home/kishor/SNAPPY/DATA/TPCH/$dataSize +#Location of the TPC-DS Data. Make sure directory name is same as the dataSize specified above +dataDir=$HOME/SNAPPY/DATA/TPCDS/$dataSize #Location where final output will be collected -outputLocation=/home/kishor/SNAPPY/OUTPUT/TPCH/SNAPPY_RESULT +outputLocation=$HOME/SNAPPY/OUTPUT/TPCDS/SNAPPY_RESULT + +queryPath=$HOME/code/snappydata/spark/sql/core/src/test/resources/tpcds + +# Whether to cache tables in spark cache or query the temp view (underlying data source) +cacheTables=true From b03f018d1ae916fba15966a8e6fd586950621ac2 Mon Sep 17 00:00:00 2001 From: Lizy Geogy <31404069+lizygeogy@users.noreply.github.com> Date: Fri, 29 Nov 2019 19:26:35 +0530 Subject: [PATCH 030/101] Add files via upload Adding an updated architecture image. --- docs/Images/SnappyArchitecture.png | Bin 103980 -> 170037 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/docs/Images/SnappyArchitecture.png b/docs/Images/SnappyArchitecture.png index 86a9965b454d073847007907497ce6cb7928a828..380d86cfae5b306296f0e875361f45c36c80de40 100644 GIT binary patch literal 170037 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%0DA&Phr2lg& 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 OD<`ESSu1Y*>i+;vBHru( literal 103980 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įE))AJ{? z3Yh6uj*W_irlu5K76}=GLi(jlOGtbWQYv-R_NcSevHoB&)B95kUKqk33#R`)OHq%5 zvwfwN)iuENaDp2e!aR~(0)Pk<-maq}RTe4)QlLelCySwqThuub;#fBhuADo2Scc3g zPvBviH)o6X4g3fDQ%~%B?eCf(I{^|CfO!`79rw(9UD#)JCaSx`w zXU%(t3?5neZt-)IwxyZSt+pLWJI~^Mv+u7x7{znavMoBrk zaR2b|a374ryon+~{kj)CO@Y~KySaTJ)7tyuFGO7PU`BX8qgZ95SmABn*U878OQG#g z&Q7Hrq&{2Uh@}rGX!s4UAXG?1m@Txf2N+yq#1T0kGn49CbCuQy^?+PvNe7@t_&AN-@FvqF-ItY}mu&p5>A)%q6 z=N|3frTM1!+VPA1J-@33g~;>QE@kI~k)95^-hcZ0&A?f*M!kTmk3lWk-K`Q|lYG{A z(-GspNbU|TOlFsyO(z=b$SU=5OEXzI2^&Gvz&`uast5KJBQ2e?Zq&KdxSA8BD%keC zph^IbdiwFzpIBRPyYXTS%RGc_Ohv@req3^q9u3KaV44AB;_5Y{P-yVXW1O`^=tAcD)}R%(>sDm{w_N3LP3sl> zD-vsuS_Ssx;xDhTrsHqDR|NRQL<-31EtpkA@3>}AAx}nk+<0<1vL{XIuJ}F`x$-}> z5wM;ng8ljB=ghRz%vbiVpZo*FAE+zR3WVAwSlF%$$<4~R6bB197{RxCi zA%MkLsnQnSpiZ_V1PcL8>I82L1js>{|94&A{0a(EF#-TtM5slU$^I}Uib;J}VI$}6 zPKC-I(1kHb5{ntMX7k2dg2ZnEP~3I7tj24d@kretsE{0>6r_v%tcY-G*rg zA%Xa93X#Ip#<99uTnhmhrRvGY{BS zoc0Aek6;M_x&T9@M!ndSjx{NF?4qM^C!{3EsNO}sJD`KfwY0DS4pdFeFz!pA{-{l6`U z>HQ^EK&0#sfa)j2V=8fr;rDr>)tNJu|LuO1thBaIn4Wjqg8y5Eau>Q_$<6;e8-A1k zS(yJ16#us~qN1q(|Ihxvp@Yvl+h{KZ$<2=b|9;bR#f3!)$wWy84?thrqKexO=HW+gPdHY2NJI&BB z1p`n+_FAtr(q*U)NWOauaWB{T<;T%kP`<2V_KH$3Ugy@ir$ zUW}NA6EQsJ>-jzihPF`YU86n@W*ovzfR$j%`WA>Pw*3WtP+E0`XK9AKRw=0PX zQofqB9Pw16_B2&eoky#&^bPH-RU>CsC1##Z`P{g!Vm=NJu;`f$BSH!B1Yb_;u-t?c z5ux`5{xPwLRUYHW8GE)^S~+z75Rew5>%)h@jreyc`?PFcrz}I&Uc?*BT!OdXh()O@ zVYw8;`9w|v4@K(KW2$7P&Uq&!zP`qW^v+D5`_#~`#z_UGvcDDvlU6II&fd?&Wx&*_ z^l6Obex>r^YdaUN$sq%c0SiFH+CiQ$ZMvsXR|`dt=6ZYOR^S{NA5TbiZShspxVI&^ zu2LFiv~lU3Cd=!OE|lVnV19f}oWSMHJ@z+UIF?j(u^9{&#`{Bl9wOq@8~R>RP@XkN zzELl1rv7QQHfZGItc4Vg*4~aDO=|Dyle@7T$lkkej&}Lc}eLF0{_FdagG41!UOp z(B;%_derD7ei85#-*Jj&sbn3ePFwD~%g-W)6K4zofQiPq z!LZM9?reyAV&OO`IW)?#{89(x)D&Wz0fNV@LywKK`N`2D z^{Ah9p&SCEzkAu2Ap!qB1i*PCFa^#u)@IiTmt7@%kt~O0czd_q@s>bAGTC{|lYp-T`Pdr8Qj>Dcg>cpRIY)DqJBuxNvmU~E4i4aTXnh7Vk_NU3N` zJYXfKN11@NEU59ZEa<_VV~b;HSX*!N|2U*I107C2UxD&MVN2{Yy6x}RqZI!>nH+YU zuOQ-`9Pfc{_-P90wy#;>XWYZO{?t2o2GpjEIK@1058#=I#W)Oj}(;`34FGSe$>B75J)At@DJuH4imI1iMtag{ zP+?r`!&6vJ8&E5^p2URmq)`+5c)Sh`TfFIfW1ks=0F-?>UvG4`VK&~cBst?w*Dlr3 zc3fQ0mvki|`ggoyfTWgBBXw6@9upo%l#6*Nhu?W8 zSo}z0h$CK}+MUL|eHpgK+2BC)6}H*vm`d){J*q$ZTi9$FP;W6TT{`Z;-mhP$69&<_ zs!oM{#_PEsr5Om;60uJ>Ol4D_!*c%!Ihf>StIa~czofgwGY4k996z8Z&%*tKxThqD zz`E~`dPLP!^4c&vU6#JJ)nrg^GrJzcl1<3xOKQ7SB$|psYMlAAtb(vpic;opY2wa_1APRjneSlYG%7MZYA_prc~o{t!Y)aAAyvO~b_=s@%WTJxxpUiOcF?L_6U;I*9Qjo`l#I;k&Al zM!Wxm|o~zB(;quH?@%&lG zJ(aWVphE;1+Mb_9M3&F{=u%=<#|!GZJzSKvyN+ch!~PgZWA7~e_^HKLAiE~Rh(dUK zYrK`h8LlB4O&a|ehNilCW#!m?Ri>JnkjvA&9pm0Oju{j4msO@#Z|ZvVrTavdbRJWw zIbUUh%&iogC3~Ah%6#ExLptZFHnP-onYV|Pgc5I=6tG`&V60`bXjwI)hp5*bSgy-ZYV;kJFLPMvOPTg zYC3B&eCd;d__-aWQI~(bK`eyC;F$(Z zK%sw{e||BpDO372aP^dOIvR&MycT*EWMv?cw_yxASLuy|6LG7pI)c9K;9m~db3-g9 ztu)Z4f7=bAl2KS|^v+^tLY$F-O^VGXuWk3*>8fiqAJGG&FezcSdl>fOh6 z>UALi+bforfj(a`gflr`X&Sk?paI)XJUmU-=$4cazQ%RhX%nye8J$m+ou@AcNt5^s zeil-%@f(!Cb8P~iCi3d#DQ$13R9z^>SC+(A~q}< zT@1RBN63R67thR*h;8Po?PS){khl^FI9+x2(DiwQ$<2o0x1W85XWbygX#szB2b6oNhzrWYUOgs82&9}Zyj_c&J$8z5sDZcg*zwI z+mXd`Ll609@5Kbu_HqB6+h$!nvJAhoQ(+z=MKnHZ_p<3xHOyP+Yhv{Ec$PGr)PAYV zHwGBN4-XA_`2SW1`B2m=kdR#6X=-~Dj|D0J;nr`oP4o3|vi$u58KXPl4Cis~bsI|3 zz>g0g?YWM+PH=OW>vC}JhKyLO@$=|~4gM)K(>7mk4hQz&q39*sN>|q^jG^r2t+|YG z3>0wLu!zkFeilf$Kh>;l2`6PBGrl;xY$qJm`zJg$b;|+(q-izvJ@v{PPl#=(o@{+?~>|PezwgDT-COxhMNCy4f z$~~@WH>LLMKtv!3ryUauMJBk#Yc~-Kl0>dj=lLjHyQ~-E(qAu})+{~XwM20&JRuB1 zB_c|xv0>NYi1W5x8PLR`^Q%Nj#u8bn3+;AjwefHBqFQu;ic!d17RY8PTl|B9%qm$q zH3{*vh9IMV-9JYF#Taq(3}U+TyeXn2AMLwm{5D-R z8Ho5?+Kh|60HJ#=`VsN^T`q&6`ay{WG@5VgrusIO_h=}1@=J2RmrW03cYXT3y&n?MpSVD^x2SSO0>FnUg(`d~X`_ z*xe?t_79gF7r#>gS>4PBqvgLDa&cQew0y^DM`6`a`hsP}FU z<(|aduYhiu%9d&Vv&pf02t==k=U%>X&sVh2)_i#w89w6f<9&9DdHoDDEbRwZPNLYG z=l9@PGlztmnYS>(7HFAR3`&N9VvX~)rV>$TlOuy}6)&b2{*PcNk_|71kAD4pTfOci zz)RcY>nXdfl15U5p@?Y~Wo26}yq5ynA&Vl3!{b1^wE0-+kMI&hd6MUe{R^lUE6zt9mMT+-Z5#(Ft3i5y4hJUAfTyi2ILRedc2NP{c#{m}%d=8S{GgYeH%y zQkToaL}9V5p_hH{`e;Ig)cQh9DI9Xv7!D)1gIe}7{Oe!?PWOk0edXp}w;o$veZNVa zR#9KIXOliWneaY05N{X`rdBlZK`(xkSbcbt?qoZ=e zcUaRw&vC(b|gc68Bs4Ckz2j0jKKSj8KT*#(CD%0OR5kS;wV`w32 zBr#p`*kENKQ-pGFa&Xfw7hD$+kBQT3dXwn02Kao-v;p~t)K+rS@4H7z!Pq6@c7M#m{At*CwUHc_K z4^-NyHC!VuIcl8=RgDhAgYM>ZhEE7)fkg~^Kva;9Pe5)s&N8Ud$wfdr5G^KX_-=|B zG1Mh!Jd!7B$!LDaJiut^s;PG-xV<={2VP6e6V^aEE6|=RH@e@CRpb*x7CR^k;~O8 z)fiOS8ybrF+E~Tg>9+wozPdrRCnNaJLa$Wn^Zj zh`0VilF4^|5WuX_hkI1tJXzFvIHXCHi&{b>kqk=>SF^wK>Mqew2zIMGPs)EdTQha4 zb&-izEYqx3VLmmTYc}XgA~Gyrj->=SNf%poKa06UrYg}aR?HV_j1u>667dJjj1?Ds zG6k|S!f&ph<#S$k=agzt5r=!{=^N&*(Ve9ma^%W-Ql?5dsB~fuZ|toTdBg~uG$zdc zy{bKoqr$=n;c|O9y6zG+e7$TrxvGIw7hv ze@+7v__=W%k{z~G9fJJT?ZJ^4GXO@FFBAQwroh%G%qA7>4?!^@9$T4Vu1bZH)mDeZ z&gLl992+E{ml+07mD#TMrpi$cqr2>uq`{HJW@iuJs!q5l_)Nh={yqvup+X?hWw2)2SKF$aDloY zgsNJOacU zQlO5RIvk*%6iwQ^y_u%L>ArkJ^2Qr^W5sRXK!7vgqz_4QgWe`x?{38f%F09^0Eij9 zdDj%AD{TpA{EdPgu-0Y?N`GbBYxQlajNraF3x0oPFuNytvKxg57arh(MwVNq1#}%l-=1CMTFzZc7|EA;>`#Cd#;pkt`JEsUh3l4Iu9o#fT^uJnI@ezh{n<=c zK9cI<_cZs1CQmwVcZ3SZHd5&kx zIBgtKEnW{3BQux!6dDSX>|E51E=0nA8FD^1>nAnM^K+*9Q0Vdg)eM`#e<_Z(b4tUW z%vQwz_&Hs<+5drY;slM;{Q2khWUg926DNV7#)OOmhE#Cdy2$(ZGVm$4f|+R_i{L^3 z+H1JUdN-L-O5=2TD=^TbA(GqSGx)E+Bx6dsR<}vc(JfW?rD$*~g5tHD!JjCvx zrbJvZ5QcoHg5655-R}4F9;A*rH)bnKTMBuNAto<7y8<#@dS(J%!eEXv zZFh)Ni%|LAmf*C*iB9Z#2L{%We*MyGZ&K?AUxM=%Hny=^6D0%T(!&gbU>BdqiK;<0 zxW$4#d)~W68zv9LklR776ZRDOuTS@TR!MW&PZryQl}b%krnclG;n=g~R?qu_j{EVF zA-HSaW;=q1F+zB|8>Wgc52-PRaZT5{i`5s`Z#eH@ZWc27r8+B_kU>I8rOvYqLR-K$ zVQDKdTvCORRl$q)@o7QMr%}n%-UFzG)vm^XPqJ?V&5t>jx8dGo9RjEKD4U-y>X#*< z-7n6szokuiIcuCeHtHE19l1RzEMMlQMKM$ZpZ(aByzjP|w*s23?(1Dnh& z?s4B%WiROs8oM<21jf6cB;soSc&zRr|8_g(&SDY@0w=C}UtS0lDaFIPc<-x^>KCx5 z0v31nO9YsG-g`TbWo$wGld;xF2sG-g6IBZY67Ev(*QNURHf%`dl3$_!mhA_;?_nFI zKq$yCJiHwx(yLTwmf|u-M>IL`k|Ctb{@VT{$>ZteVWn%>1wv-0PTWyka@uZSF+mLc z$izqJm_FU=G9N#?T%2aW;w>|E*QW$CDrBgVeSd!s@)WCi^LSZZSZg}tc0Lh#IZd_< z&?vg_Eo$ST=QE{h6)Q(zg!X@!T-7wleAxMG87gj4;`ag7ANzASH!#0_F|$C!dePZ& zL1(LWv-9$*)is^PqU*L>F|dNq@kXfR6y7*CP&F2{97qO``1lnaRD<{GS;Bt#Z?;#t zyD*(TQ>|6aj}%)`$XgrhMRiSVBQFz-dgvA%yK!}T71HzV z2d_+Z9{XM4#QWW31ufo6fr1dAPI+fWc(o|B)Wb@nbyajSJdS4P`bk!-%|h<;X}yj| zeT=g9=~sYN-kNicI$I14?H34kehz(T2;WkQWd_)$}XCqgNtj(pXaOA zi-e}_vYiFvfgp=H&3#A!lvH#=jbQ`ZgRf*Km(A-(Lp!IP^t6XzD)Z3e$IlRlUv28L zidmnh2-+KY9?ovvDX|;YFqL2UdE6&&>VDw{0oX+EM-5WRg}V42WiQ`r-C<}^0WxJ( zFOHS@xBzte#hBNoStDOLE!562TndWu@99y-u*Qui3te6|S2GPb9TM^g|0y-gl(m~; z_n@Jf?E7L)!h0c~dGKQQB!ilDsyjqOPSNlNDB(P)Ajw0L=`_-@`~(sV8F6Ql2FbOc zD{QpTh37f~umI4?Ng?)}sq_>Q0r5DWnx2J;p^tI-^(_i97S#kx)~i)rTglz#r(HND ze$E^X;wDU&b53C{6to%)TfcHD7x(fnczx=$5483KQ?~$Q-=iTT(3m52M&^2MJ9=CJ zbV@`-t~n#FSsrs_*2>#Rp>G14Avj*Y{%&7!4{2?4%g=G=fl$lZlz-)WT7020oFPOeFhcC9;t);&p8AA^al=d)8_oYPsvO*X ze7f9OE{GMET=vd3-#9dFTur~Cf`(ukHeV`kjqsK7Jy?sA8>)1DOPOVI@Q-V$T zp;pG`dve=dwb67EVR#sjk*`-Uw9EP0as42>RlVF10Qx`y%M^AwR7-zruX(+Q7^FqP zk&Tw6O56Su6*~;*3DRa>gcr@g1FD2Viln#@PMaEG25&o=WML?kMMm-AN~Lr??>8t0 zaG%9SN-+?VVC{09s9ruxE6PaOg|UDw*clUYi-A8DK+YzB~B|a#6u&$eb}8RdsKsiOhie z=uY(kg1jeB4eI?gOElx+<&W0evUbv`q4IFz3HknbZ+X*2v)gD?Dl@#i&0y$0-;`8doSTPA5V||;(-|;FFM!kxalBGrOix+N!CM{?|bmJN;FK+Xy;-*U2_{y zF51ZgO$OM8x!&&T#HoL4JeeQk_uT!P{kKL{g8kyXFmvzun`FFShnaryk2nHsN#X>C z)id_frO0i|<2KxP6h`H53#|!EMu^`C zsXq0XLJe(Q2X^~Hn+#-zfqFASJBIlDmKARWir-J3T*X|M(J2HWb7h{yoO?f>QSc<%qpYm);KL z?u;<378UWZPSzMgs>qx!k zA|3Wu#~p|unhM25FmY{$f7=UJNc$G0L0wUDRdW?jPpb&o0RZSHL; z@IOA~-hPNs*@GSgOb;Uluq%}&u4je?10VETGi&c-5bOQ<0;ekT&uTRrfxNV~Q-ufq zFAqd3EM~i}vW$fpAfB|Fae_s*!0lEsT+xDDFBp8M&UE>q4z+;kZmjzcz=25jGBb5P^nbHVYU%)#N=|X9=6Oz zeIVstmEU>H#xtuj_iKIf>O=I#3QexJU7?N133e|gt78q)QFSk!W41v;k2D)_9-hVD zZHOI9VqQG(?z>CgU-FgaJ_q{uR5#9(ZIorOYlr znTWo+tKADh!ZT1%lm|>=)~;3B__$=wCx%wx0w7SKuj`oQPc_-z0$lRL2%@o1r)AS) z^BZUsixQP*l7A#vDUlE4r@s%KvUaUIK{~et?1f|G9iif%d7TeB``E>$hc}vJUC)Ii z1V}XpGL@Kj9!{rL>NyOe*seXEem-CzQFgH1#>7dQMeF>v;@(SjfW*~Zs`7O>N#Y9& z6CaY#<@&AT(n87U|F1`zciQ|LaHoe*vMb8Y7rY8{58IftQPI zf=(KmSivS^(Wd@mv5fwpI#QQMSx)1WFW2URey!ubVF*eTU$0XAGI0if{|0J?bCm0F zsPV;(tg1QQTOBF=XP6BxtTU@^sdn`XcK*BqsE^S(=e&tneE z=wp)>Of#k`#&7g`M!3Z3KFei!b@Ec1zyUWYxZZhM#O8nx7RRZV*&P>ouM*qFRd!3h z+OAHoHDELL045`|gH+`~wj!}$etHTx2S-i?LrT}?<@b#{1-(qKbS4FD=tlh%kq!}W zR#L+|R?0<&8hzhr;Ocp#oi#6?<8hdJP5?O}D*sbwYq0xwxwrSoPTR1=7TAjyi&|Pt zSdG&A3QOC5riS91*aFgi^x0NtSj};pLkgXKlO4^CPwH=#Vwp7Y3X8WP&QPM>4IcI- z_jix12xfddtc^y0ypqGn3Jeh>Flt^8dv~<{g+R5#frz-OBc&R61pyPt-G`RLc z>TvOz-}!PlJDHCdU^+W&JKfiTSCkv>Im`Ri;H5{vQcbe9rpR_Q6HQ5<)y-&Lawc(Z zg^}-5D=yr96D-t2!r(Ml+KD^0{%z>vGVD_vsg}NrX)l5};nDxM@bSSG9m(BW6}zE= z9@p!)K(XEFISETbZnlp=+JIHHCf820Nv3hzZ1j^_;kds=rF!$S@EG4ej=~7PFaU&b zTN~;*9Qo~BO+0;G;)}HT;ZoReF(}^NYvGV2&6>m2AN*cchWsgQ(qnee;^pL8JGRFy zDeEon$5Q2Fynb5_V|xcI{DL=i%zN$GN%r^(3lO>c8CiB@v=-Phh&pR#*ywYA!shVH znuk;YovXVFKLyX=xgefM*Tc>c^^Z)>^rzui1$AWF!d8`7L0y8UBb9Fl5W*5A_kGAo z5cFHlN$0qhz;giRR$V2T=kA;+)hBxCfK1U%kLPZ#I)b$V$5TiAvoDp>7tt2o4nqC) z+$^D5xHk4|~$Iw!mR!K$j#=c*h{=O8H_pp;QMKZxHq*yd_jWkcDx?u zw-Ol%FB=&%ixo(ge#D=}>b8KE&-Kun6kdPXS7&(+)bo;SiEiTw zuMOn=Aq*w@9}lJH>NKf-myMMDMWJpcCtz~;`vC{bK82xQH&8!2iP}7>(FOu=_{1uS z!gqTT+@lEYyckP^FG5Vo$+731<>8+l?2}3mpwG|gd>@Tp&_lL;rdcTIma_D}IzM99 z4ar&jS9XM#oZqAk;kpjCfrk^!$G)n!jjq+dG z-FkBLCr1Wn8C}jp*jWZdZrK0;Ub2&t$pGxG^T|I!2FdJ;^tSN0eilp6|&z}@O zD6th|OM{q0b`_Q!t0fDfveDFGQndIOu3|>;32{jZj1>S`8Mt1OCA2WveUZxV1~nb< z*W*ic-Ag~ePGnV30RT(!lLSlb1MKuhPqpt~m=RY1046hTCnRP!!)?3`DqKl1<*)mN zB^9fU`yFzvA05usNI%iN41s{4S=+$uB_=@6Df5K)hk&|Liqj7D_#r>@eQ0WOiGv3W zI1HoWbW~xqXp~Pm03LBl_TW>3IWXdj0>z68H$;t-vg@(cAROUR=WqB+du7o`q( z7Q`wD*IUx8TS)>te_YurUtdq;Zrxr(1O$vy<_A1pgG9u{My@R38q0C*eG0%4hGucl zeioPaSwE6Yh;Z)@e}4a|Qpq=fkXxtA#t#z3Bje`l&79b!AJdo2eiwC@23#%-um8$# zqiX1jeq5@Vb$>3;*yH%qk88PyE|lrMW@}7F2|5l=69~Nd=!4KMNwjYWXYRkS6EI}m zS^Xq}A|1jl7F(E5{r>{u4ju8e_osgi0pn1i4G%&Hp^QTiS0?q><+INoJF#-hfu+mV zjhvV{bNs-BFgEz%`fvVv$W5Cq{B(6{lXgiC>h;|ErLCg&-0YRnA;ONmyVK58N{+M# zv;&DueWZ-ztJUk08bvuuCnpHxKCc3F=j`A&C(WYQ&Q<~ZnVjP6HhI*TnH9sNXihlT z>(1JLN}2z`B;N2Zc<@tF@2@|+J>NRlx1jhS=5-JvRq#)P)rI*l3H z4$hp;Kq3MF2D(9Xo#?t@823TNDwA8G>FPsO%V)Z;>^Yuo6?ue^z`^20pG^O1*QMP% zo|&}ZvX{muCJyS`WyR+c^DbS?$@KtZrRp`LmoFV!^Yf4A>C=xiReUNi5JW-bxk6?i z2^`Fr^1n;EbHV$sMS3pJ_+%aMd_b!C^W|>6TI^o2@%wGZs+FrqfrG+D7`<^*pt#9&B zO{Qp-lZ$QHeQ@oT!<*J`T(~|>#2A1X1|gIJFlLGASGU;011u*}D6X?Ru?wO=At}SHQ${MBSbH zcekL1o>;S9?dTt-y!-JBgWH#lv94V4>)dY+jv3cDzO=Ay?1xilMfQ2PwhN3k>wc9& zLhKGJ1F%_a^{U3bGJ9pIiq&f*OP)MgvWgpj-slaBZCfo-(Fp)>nC;rQY3|CC(`LS$ z8e@HKWVgr1e>(fe(xY1@0w7|jmFhQ)qF*fAV0-74#+cIr=l&7GM9$y6EiKQl0b_za zsAk!?KNq!N`fN;0?wZbFh@yYSF-&x=e63ouCmLUTzjpdw8|B1FuM908Da7>a$u0SL z-r}E}0xMs$-k=`MD5K3gv^6+|di^Zk#H80`3Z z)%-=v7%?6l(!WoKT6RvK`}%;ni`S>^v@^s_eQR`$5SskrbMJrp(}y4bKsBv=)7Fo5 zs!rAa|5h&pjd21(3>D?s#*|QhOqM&hpfDLi$mjRv0jh{4c z&{GpJMgZc7;r-gwO5%WhG2^L`lNSH9d=-b0#Thhy%-~Y7L4;7=Vyji9eFayjapAUwC|OPlM|!f^?CfN zPGrN{u3^eor>(IuQNYe#$#km-%Zi+FY=5ueX^a6QhFGd*+NZ;`eDzP63P%Tt+y$N$_`vaHeu4eL~^Q7vGBtQJvKbZ1cTfc{+I#G#g!-d7)xbOVeW!c9f#4*? zuRK2T>A^gB^8M|4Kjt1X46fHd14Z%48m`hZeNTHe&#RMb_0K#wZ0E*>U}$;y@}QxQ zKl#j{yd1A+m8_EB^T~`sohEHP=eph$+=0QD;bwm+n;8aVnAV`s4I~UGI%R;s zo8x6H8QgUV|rw_j_Kr@mUQm-|fSH;-fOg0Gqz3n`DAP5Hg3&ZJ-7NjLrV?dvX<| zQsj~VA%yWiwUbU6SS;d=!3)3`<9MFqq41Lc!1FxMUt3E{0?!y&um9q8J&dnEbM1F1 z1B)d7<{denxAFz={{O!59EKg2Ifn$17F@Kgktw16*a&;F-32E_5kj)xA8>4_ilWFj zj#dS(A-d|xRthJ@$B21y@&FKrkfy1s2E4!%-SA#745DkQmigPd;(s}WQ&`~CGVx@&5kk7`Xa2%>8T~o^1Rf3S z5<&>f>J0@(B3Bpe0y48O-@+UMJL?rA9LStde&>RMJ?UJ6lb0}J=9z{9Re|A>2Y-50 zdblLdFo!WN!t;zNq5gyw{@v|I=uSfCR@bA#ev#jgw7b>A5CXRhXY+A#Fs9~`8UO$e zWpiN`9wUShy1ONxZZ~7zvfxzV_x0s_M!qycy*Ur^?YhlPo#%HQ?=O5Dl|Z`8mk%+! z#*J3Jn2$UCDc#*uZ{dWCzw4hMg(aUPK7<1k$H;+5xx`mvlK3LMAXxp5GH zh*1$&SqKoo_AA^sr^FiJB+-RM$#TstW=bfN`yUa*tiw{R7;NE8V*m`mt>T^OLX!k6 ziQ*s5asQ?$_ur#D$Oys79DL3rv~qA}4+%5~CFs2amez?_63qGVw+I+!9h6eTQJ9TK z=#Mw50zq~d7v+A181Nk1eHrE*mTH8O`1| z2EqV!LVTsd9Cl}rBuUp!Vwn=^zpRX}8PuZv8FdOP&j}avQQtBgFG;uCm`4vrEV0hO zqv8MUlcFRj79@zG_<*mQ5dZ-==SJ@xkh&y;%PRiCr2ha!1{nB1S6EC;BSxf7On`-w@fzh-Ykv*Y8)Y#374Es zr^RBqgHT|A;+2ykx#Bp2^9wtRu zLIt|BYM^uZh%sDbr#%J+Lzyz{&qNn;QJZ+?uv;X_!t=Kd0J`i&JJb0hyh>yMvH|HH zwEYTSCP=RzD>|-^yt3ZQ_-;;yyYTp8KajBvxw5IEMj2m5Wua$ z_A9(fit^;(Cy?&JyRM>SyVf9vw>VrD>mP4AAOOZ-XF3NAu_CGy0_(9{1s%=8`3h?n zr&<56y>sW0qz2-+%XazM4|mTkw;Gn^kVqjRgkYnE1c|T7S0Fr*@dXHwP9nI3L)trn zo$emn1m=bn%wu`#&Rf4|k_lX0{@1_C(;k0jtvxkpVZn$`&h?K!O|Q1wRPT`$LcAK; z+Qz2q`(f4hy)ous%L>3bcUoOv%A1=!%}cKG-ai0fj0+)AJ3sb)A42fnzd5sivQU4g zl(t%omVf;{#u%Z>U;Dvt?;LMqeyld1ujTm=y4PF!&$+v@ywmvf*_2YOb}*NLr8KB? z{TMES?T4{#Tcy-~jRSV>)wj==@1CcMe+`-$V=;Ad{_+AY#-`~9=iFYqkW&tZe{_c5 z{E%YWvMOVe8Do%H>Uq36T07@k57lImQ-xUyI`6%d@`!~JLOAD^FiLG>jJ4`a zS*cP=Ywf+)S|j3r_m(1AsQ=@cI^Te=B3uN2w)je8l`;GlxE0UyLTp68pKc6_#tj@Z*OC@cbNhgpip|P zy0#t0vF{F=Y~b8$yuK7SFPCMWD|VF{5m9;X?{>_`6(2a~LVotHd|~2dGo_Sj-9#L~ zXmr-LT^B+))`a}7Lc%#0hfy25-EJ#xNQ4lGsFZTfoiqvnAf+_MAmTjFIp>NkR9UQ) zQV4PA7=$d;+p{()tu?FAD#4az$tl(P#!;!|-GQmTGQnB7F-o?k3EQ~j*v?uYw(FM0u%EYw@pE)%qMGyo*5CrkB!zly=K@bE%5M-eUf*=Tj kAjm=y1VIo4LA-hV3SYaoOiG1pM*si-07*qoM6N<$f(YBr^#A|> From 693c3eb5fbe1d4665067f146f5fe1d3515109d31 Mon Sep 17 00:00:00 2001 From: snappy-sachin Date: Sat, 30 Nov 2019 00:43:10 +0530 Subject: [PATCH 031/101] Fixes for SNAP-3253: (#1491) * Fixes for SNAP-3253: - Adding method updateStructuredStreamingUITab which calls parent classes method updateUIWithStructuredStreamingTab using reflection. This method creates or updates Structured Streaming UI Tab. - Adding call to updateStructuredStreamingUITab for each SnappySession object creation. - Updated log message to indicate that spark distribution used is not snappy-spark distribution, if UI is unable to add Structured Streaming UI Tab. --- .../org/apache/spark/sql/SnappySession.scala | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/core/src/main/scala/org/apache/spark/sql/SnappySession.scala b/core/src/main/scala/org/apache/spark/sql/SnappySession.scala index 6e0f698b62..4bff5c9120 100644 --- a/core/src/main/scala/org/apache/spark/sql/SnappySession.scala +++ b/core/src/main/scala/org/apache/spark/sql/SnappySession.scala @@ -16,8 +16,8 @@ */ package org.apache.spark.sql +import java.lang.reflect.Method import java.sql.{Connection, SQLException, SQLWarning} -import java.util.Calendar import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.atomic.AtomicInteger import java.util.{Calendar, Properties} @@ -2169,6 +2169,25 @@ class SnappySession(_sc: SparkContext) extends SparkSession(_sc) { } (scalaTypeVal, SnappySession.getDataType(storeType, storePrecision, storeScale)) } + + /* + Method to add/update Structured Streaming UI Tab if cluster is running in embedded mode or + smart connector mode using SnappyData's Spark distribution + */ + def updateStructuredStreamingUITab(): Unit = { + try { + val updateUIMethod: Method = super.getClass.getMethod("updateUIWithStructuredStreamingTab") + updateUIMethod.invoke(this) + } catch { + case e: NoSuchMethodException => + logWarning("Unable to add Structured Streaming UI Tab because " + + "updateUIWithStructuredStreamingTab method is not present in SparkSession class. " + + "It seems spark distribution used is not snappy-spark distribution.") + } + } + // Call to update Structured Streaming UI Tab + updateStructuredStreamingUITab() + } private class FinalizeSession(session: SnappySession) From 9bc75c57a65e1735c39a40d79cb74f56fd7d0205 Mon Sep 17 00:00:00 2001 From: Sachin Kapse Date: Sat, 30 Nov 2019 00:48:52 +0530 Subject: [PATCH 032/101] Linking latest spark submodule. --- spark | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spark b/spark index ec4f6cd87e..c53000d0a4 160000 --- a/spark +++ b/spark @@ -1 +1 @@ -Subproject commit ec4f6cd87e527c218d785d296c8d4594f7eede55 +Subproject commit c53000d0a4dcd79142b71e9acb3bc9ee0f4d0234 From 5a1a87069612e0bbed1c9461dc21029278e77536 Mon Sep 17 00:00:00 2001 From: snappy-sachin Date: Sat, 30 Nov 2019 01:16:44 +0530 Subject: [PATCH 033/101] Fixes for SNAP-3147: (#1486) - Removed start date-time value created and stored in HTML Page. - Code cleanup and refactoring --- .../apache/spark/status/api/v1/ClusterDetails.scala | 1 + .../org/apache/spark/ui/SnappyDashboardPage.scala | 11 +---------- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/cluster/src/main/scala/org/apache/spark/status/api/v1/ClusterDetails.scala b/cluster/src/main/scala/org/apache/spark/status/api/v1/ClusterDetails.scala index d90a1d7252..8292dfa4fb 100644 --- a/cluster/src/main/scala/org/apache/spark/status/api/v1/ClusterDetails.scala +++ b/cluster/src/main/scala/org/apache/spark/status/api/v1/ClusterDetails.scala @@ -34,6 +34,7 @@ object ClusterDetails { coresInfo += ("totalCores" -> csInstance.getTotalCPUCores) val clusterInfo = mutable.HashMap.empty[String, Any] + clusterInfo += ("startDateTime" -> csInstance.getStartTime); clusterInfo += ("coresInfo" -> coresInfo); clusterInfo += ("timeLine" -> csInstance.getUsageTrends(ClusterStatistics.TREND_TIMELINE)); diff --git a/cluster/src/main/scala/org/apache/spark/ui/SnappyDashboardPage.scala b/cluster/src/main/scala/org/apache/spark/ui/SnappyDashboardPage.scala index e4309159ea..1d0e556650 100644 --- a/cluster/src/main/scala/org/apache/spark/ui/SnappyDashboardPage.scala +++ b/cluster/src/main/scala/org/apache/spark/ui/SnappyDashboardPage.scala @@ -19,7 +19,6 @@ package org.apache.spark.ui -import java.util.Calendar import javax.servlet.http.HttpServletRequest import scala.xml.Node @@ -29,14 +28,11 @@ import org.apache.spark.internal.Logging private[ui] class SnappyDashboardPage (parent: SnappyDashboardTab) extends WebUIPage("") with Logging { - private val startDate = Calendar.getInstance().getTime() - override def render(request: HttpServletRequest): Seq[Node] = { val pageHeaderText: String = SnappyDashboardPage.pageHeaderText // Generate Pages HTML - val dataNode = createHiddenDataNode val pageTitleNode = createPageTitleNode(pageHeaderText) val clusterStatsDetails = { @@ -83,7 +79,7 @@ private[ui] class SnappyDashboardPage (parent: SnappyDashboardTab) UIUtils.prependBaseUri("/static/snappydata/snappy-dashboard.js") }> - val pageContent = jsScripts ++ dataNode ++ pageTitleNode ++ clusterStatsDetails ++ + val pageContent = jsScripts ++ pageTitleNode ++ clusterStatsDetails ++ membersStatsDetails ++ tablesStatsDetails ++ extTablesStatsDetails UIUtils.headerSparkPage(pageHeaderText, pageContent, parent, Some(500), @@ -153,11 +149,6 @@ private[ui] class SnappyDashboardPage (parent: SnappyDashboardTab) } - private def createHiddenDataNode: Seq[Node] = { -

- } - private def clusterStats(): Seq[Node] = {