Rename package and make-dist with maven offline mode
[aquarium] / src / main / scala / gr / grnet / aquarium / store / LocalFSEventStore.scala
1 /*
2  * Copyright 2011-2012 GRNET S.A. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or
5  * without modification, are permitted provided that the following
6  * conditions are met:
7  *
8  *   1. Redistributions of source code must retain the above
9  *      copyright notice, this list of conditions and the following
10  *      disclaimer.
11  *
12  *   2. Redistributions in binary form must reproduce the above
13  *      copyright notice, this list of conditions and the following
14  *      disclaimer in the documentation and/or other materials
15  *      provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
18  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
21  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
24  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
25  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
27  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28  * POSSIBILITY OF SUCH DAMAGE.
29  *
30  * The views and conclusions contained in the software and
31  * documentation are those of the authors and should not be
32  * interpreted as representing official policies, either expressed
33  * or implied, of GRNET S.A.
34  */
35
36 package gr.grnet.aquarium.store
37
38 import gr.grnet.aquarium.Configurator
39 import java.io.{FileOutputStream, File}
40 import gr.grnet.aquarium.util.{Loggable, stringOfStackTrace}
41 import gr.grnet.aquarium.util.date.{TimeHelpers, MutableDateCalc}
42 import gr.grnet.aquarium.uid.{EAIOUUIDGenerator, UIDGenerator}
43 import gr.grnet.aquarium.event.ResourceEvent
44 import gr.grnet.aquarium.event.im.IMEventModel
45
46 /**
47  * This is used whenever the property `events.store.folder` is setup in aquarium configuration.
48  *
49  * @author Christos KK Loverdos <loverdos@gmail.com>
50  */
51
52 object LocalFSEventStore extends Loggable {
53   private[this] final val UIDGen: UIDGenerator[_] = EAIOUUIDGenerator
54   private[this] final val NewLine  = "\n".getBytes("UTF-8")
55   private[this] final val NewLine2 = NewLine ++ NewLine
56
57   private[this] def writeToFile(file: File, data: Array[Byte], appendString: Option[String] = None): Unit = {
58     val out = new FileOutputStream(file)
59     out.write(data)
60     appendString match {
61       case Some(s) ⇒
62         out.write(NewLine2)
63         out.write(s.getBytes("UTF-8"))
64       case None ⇒
65     }
66     out.flush()
67     out.close()
68
69     logger.debug("Wrote to file {}", file.getCanonicalPath)
70   }
71
72   private[this] def createResourceEventsFolder(root: File): File = {
73     val folder = new File(root, "rc")
74     folder.mkdirs()
75     folder
76   }
77
78   private[this] def createIMEventsFolder(root: File): File = {
79     val folder = new File(root, "im")
80     folder.mkdirs()
81     folder
82   }
83
84   private[this] def writeJson(tag: String,
85                               folder: File,
86                               jsonPayload: Array[Byte],
87                               occurredString: String,
88                               uid: String,
89                               extraName: Option[String],
90                               isParsed: Boolean,
91                               appendString: Option[String] = None): Unit = {
92     val file = new File(
93       folder,
94       "%s-%s%s.%s.%s.json".format(
95         tag,
96         occurredString,
97         extraName match {
98           case Some(s) ⇒ "-" + s
99           case None    ⇒ ""
100         },
101         uid,
102         if(isParsed) "p" else "u"
103       ))
104
105     writeToFile(file, jsonPayload, appendString)
106   }
107
108   def storeUnparsedResourceEvent(mc: Configurator, initialPayload: Array[Byte], exception: Throwable): Unit = {
109     for(root <- mc.eventsStoreFolder) {
110       val uid = UIDGen.nextUID()
111       val occurredMDC = new MutableDateCalc(TimeHelpers.nowMillis())
112       val occurredString = occurredMDC.toFilename_YYYYMMDDHHMMSSSSS
113       val rcEventsFolder = createResourceEventsFolder(root)
114       val trace = stringOfStackTrace(exception)
115
116       writeJson("rc", rcEventsFolder, initialPayload, occurredString, uid, None, false, Some(trace))
117     }
118   }
119
120   def storeResourceEvent(mc: Configurator, event: ResourceEvent, initialPayload: Array[Byte]): Unit = {
121     require(event ne null, "Resource event must be not null")
122
123     for(root <- mc.eventsStoreFolder) {
124       val uid = UIDGen.nextUID()
125
126       val occurredMDC = new MutableDateCalc(event.occurredMillis)
127       val occurredString = occurredMDC.toFilename_YYYYMMDDHHMMSSSSS
128       val rcEventsFolder = createResourceEventsFolder(root)
129
130       // Store parsed file
131       writeJson(
132         "rc",
133         rcEventsFolder,
134         initialPayload,
135         occurredString,
136         uid,
137         Some("[%s]-[%s]-[%s]-[%s]".format(
138           event.id,
139           event.userID,
140           event.resource,
141           event.instanceID)),
142         true
143       )
144     }
145   }
146
147   def storeUnparsedIMEvent(mc: Configurator, initialPayload: Array[Byte], exception: Throwable): Unit = {
148     for(root <- mc.eventsStoreFolder) {
149       val uid = UIDGen.nextUID()
150       val occurredMDC = new MutableDateCalc(TimeHelpers.nowMillis())
151       val occurredString = occurredMDC.toFilename_YYYYMMDDHHMMSSSSS
152       val imEventsFolder = createIMEventsFolder(root)
153       val trace = stringOfStackTrace(exception)
154
155       writeJson("im", imEventsFolder, initialPayload, occurredString, uid, None, false, Some(trace))
156     }
157   }
158
159   def storeIMEvent(mc: Configurator, event: IMEventModel, initialPayload: Array[Byte]): Unit = {
160     require(event ne null, "IM event must be not null")
161     for(root <- mc.eventsStoreFolder) {
162       val uid = UIDGen.nextUID()
163
164       val occurredMDC = new MutableDateCalc(event.occurredMillis)
165       val occurredString = occurredMDC.toFilename_YYYYMMDDHHMMSSSSS
166       val imEventsFolder = createIMEventsFolder(root)
167
168       writeJson(
169         "im",
170         imEventsFolder,
171         initialPayload,
172         occurredString,
173         uid,
174         Some("[%s]-[%s]".format(event.id, event.userID)),
175         true
176       )
177     }
178   }
179 }