--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/scala/radview/model/Cdr.scala Sun Apr 03 15:55:02 2011 +0200
@@ -0,0 +1,188 @@
+/*
+ * Copyright 2011 Tomas Zeman <tzeman@volny.cz>
+ *
+ * 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.
+ */
+package radview.model
+
+import java.util.Date
+import net.liftweb.common._
+import net.liftweb.mapper._
+import radview.snippet.SessionSnippet
+
+/*
+ Table: v_radacct
+ */
+object Cdr extends Cdr with LongKeyedMetaMapper[Cdr] with Loggable {
+ override def dbTableName = "v_radacct"
+ override def dbDefaultConnectionIdentifier = RadAcctConnectionIdentifier
+
+ def bySession(s: CdrSession) = findAll(By(sid, s.sid),
+ OrderBy(radacctid, Ascending))
+
+ def fieldsForList = List(sid, ts, inBytes, outBytes, statusType, acctuniqueid,
+ username, groupname, realm, nasipaddress, nasportid, nasporttype,
+ acctsessiontime, acctauthentic, serviceType, framedProto, framedIp,
+ statusType, cell)
+
+ import java.sql.{Date => SqlDate}
+ implicit def d2sqlD(d: Date): SqlDate = new SqlDate(d.getTime)
+
+ private def diff(col: MappedField[_, _]) = String.format(
+ "MAX(%1$s) - MIN(%1$s) AS %1$s", col.dbColumnName)
+ private def min(col: MappedField[_, _]) = String.format(
+ "MIN(%1$s) AS %1$s", col.dbColumnName)
+ private def max(col: MappedField[_, _]) = String.format(
+ "MAX(%1$s) AS %1$s", col.dbColumnName)
+
+ def sessions(from: Date, to: Date, field: MappedField[_, Cdr],
+ value: String) = findAllByPreparedStatement { sc =>
+ val selectS = List(sid.dbColumnName, diff(inBytes), diff(outBytes))
+ val sql = String.format(
+ "SELECT %s FROM %s WHERE %s = ? AND %s BETWEEN ? AND ? GROUP BY %s",
+ selectS mkString ",", dbTableName, field.dbColumnName,
+ ts.dbColumnName, sid.dbColumnName)
+ logger.debug(sql + "; params: " + from + ", " + to + ", " +
+ field.dbColumnName + "=" + value)
+ val stm = sc.connection.prepareStatement(sql)
+ stm.setString(1, value)
+ stm.setDate(2, from)
+ stm.setDate(3, to)
+ stm
+ }
+
+ def session(sessionId: String): Box[CdrSession] =
+ Box(sessions(List(sessionId)))
+
+ def sessions(sessionIds: List[String]): List[CdrSession] = sessionIds match {
+ case Nil => Nil
+ case xs =>
+ val cdr1 = findAllByPreparedStatement { sc =>
+ val selectS = List(sid.dbColumnName, diff(inBytes), diff(outBytes),
+ min(radacctid), max(ts))
+ val sql = String.format(
+ "SELECT %s FROM %s WHERE %s IN (%s) GROUP BY %s",
+ selectS.mkString(","), dbTableName, sid.dbColumnName,
+ sessionIds.map(r=>"?").mkString(","), sid.dbColumnName)
+ logger.debug(sql)
+ val stm = sc.connection.prepareStatement(sql)
+ sessionIds.zipWithIndex.map { r => stm.setString(r._2 + 1, r._1) }
+ stm
+ }
+ val cdr2 = Cdr.findAll(ByList(radacctid, cdr1 map { _.radacctid.is }))
+ val tsMap = Map[String, Cdr]() ++ (cdr2 map { c => (c.sid.is, c) })
+ for {
+ c1 <- cdr1
+ c2 <- tsMap.get(c1.sid.is)
+ } yield {
+ CdrSession(c1.sid, c2.ts, c1.ts, c1.inBytes, c1.outBytes, c2.cell)
+ }
+ }
+}
+
+class Cdr extends LongKeyedMapper[Cdr] with CellAware {
+ def getSingleton = Cdr
+ def primaryKeyField = radacctid
+
+ object radacctid extends MappedLongIndex(this) {
+ override def dbColumnName = "radacctid"
+ }
+
+ object sid extends MappedPoliteStringColName(this, 64, "acctsessionid",
+ "Session Id") {
+ override def asHtml =
+ <a href={SessionSnippet.url(is)}>{super.asHtml}</a>
+ }
+
+ object acctuniqueid extends MappedPoliteStringColName(this, 32,
+ "acctuniqueid", "Unique Id")
+
+ object username extends MappedPoliteStringColName(this, 64, "username",
+ "User")
+
+ object groupname extends MappedPoliteStringColName(this, 64, "groupname",
+ "Group")
+
+ object realm extends MappedPoliteStringColName(this, 64, "realm", "Realm")
+
+ object nasipaddress extends MappedPoliteStringColName(this, 15,
+ "nasipaddress", "NAS IP")
+
+ object nasportid extends MappedPoliteStringColName(this, 15, "nasportid",
+ "NAS Port Id")
+
+ object nasporttype extends MappedPoliteStringColName(this, 32,
+ "nasporttype", "NAS Port Type")
+
+ object acctsessiontime extends MappedIntColName(this, "acctsessiontime",
+ "Session Time")
+
+ object acctauthentic extends MappedPoliteStringColName(this, 32,
+ "acctauthentic", "Authenticator")
+
+ object inBytes extends MappedLongColName(this, "acctinputoctets",
+ "Input bytes")
+
+ object outBytes extends MappedLongColName(this, "acctoutputoctets",
+ "Output bytes")
+
+ object calledNo extends MappedPoliteStringColName(this, 50,
+ "calledstationid", "Called No.")
+
+ object callingNo extends MappedLongColName(this, "callingstationid",
+ "Calling No.")
+
+ object termCause extends MappedPoliteStringColName(this, 32,
+ "acctterminatecause", "Termination Cause")
+
+ object serviceType extends MappedPoliteStringColName(this, 32,
+ "servicetype", "Service Type")
+
+ object framedProto extends MappedPoliteStringColName(this, 32,
+ "framedprotocol", "Framed Protocol")
+
+ object framedIp extends MappedPoliteStringColName(this, 15,
+ "framedipaddress", "Framed IP")
+
+ object startDelay extends MappedIntColName(this, "acctstartdelay",
+ "Start Delay")
+
+ object stopDelay extends MappedIntColName(this, "acctstopdelay",
+ "Stop Delay")
+
+ object corrId extends MappedPoliteStringColName(this, 64,
+ "3GPP2_Correlation_Id", "3GPP2 Correlation Id")
+
+ object statusType extends MappedPoliteStringColName(this, 15,
+ "Acct_Status_Type", "Status Type")
+
+ object ts extends MappedDateTime(this) {
+ override def dbColumnName = "Event_Timestamp"
+ override def displayName = "Timestamp"
+ }
+
+ object releaseInd extends MappedIntColName(this, "3GPP2_Release_Indicator",
+ "3GPP2 Release Indicator")
+
+ object activeTime extends MappedIntColName(this, "3GPP2_Active_Time",
+ "3GPP2 Active Time")
+
+}
+
+case class CdrSession(sid: String, start: Date, end: Date, inBytes: Long,
+ outBytes: Long, cellId: String) {
+
+ def cell: Box[Cell] = Cell.findByKey(cellId)
+}
+
+// vim: set ts=2 sw=2 et: