Skip to content

Commit 6c00965

Browse files
committed
refactor soft deletion of searchindex
1 parent 59a33f0 commit 6c00965

File tree

6 files changed

+78
-88
lines changed

6 files changed

+78
-88
lines changed

src/main/scala/com/cloudant/clouseau/ClouseauTypeFactory.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ case class RenamePathMsg(dbName: String)
3434
case class CleanupDbMsg(dbName: String, activeSigs: List[String])
3535
case class DiskSizeMsg(path: String)
3636
case class CloseLRUByPathMsg(path: String)
37+
case class SoftDeleteMsg(path: String)
3738

3839
case class Group1Msg(query: String, field: String, refresh: Boolean, groupSort: Any, groupOffset: Int,
3940
groupLimit: Int)
@@ -95,6 +96,8 @@ object ClouseauTypeFactory extends TypeFactory {
9596
Some(DiskSizeMsg(reader.readAs[String]))
9697
case ('close_lru_by_path, 2) =>
9798
Some(CloseLRUByPathMsg(reader.readAs[String]))
99+
case ('soft_delete, 2) =>
100+
Some(SoftDeleteMsg(reader.readAs[String]))
98101
case ('commit, 2) =>
99102
Some(CommitMsg(toLong(reader.readTerm)))
100103
case ('set_update_seq, 2) =>

src/main/scala/com/cloudant/clouseau/IndexCleanupService.scala

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,6 @@ package com.cloudant.clouseau
1515
import com.yammer.metrics.scala._
1616
import java.io.File
1717
import java.util.regex.Pattern
18-
import java.text.SimpleDateFormat
19-
import java.util.Calendar
20-
import java.util.TimeZone
2118
import org.apache.log4j.Logger
2219
import scalang._
2320

@@ -31,19 +28,6 @@ class IndexCleanupService(ctx: ServiceContext[ConfigurationArgs]) extends Servic
3128
val dir = new File(rootDir, path)
3229
logger.info("Removing %s".format(path))
3330
recursivelyDelete(dir)
34-
case RenamePathMsg(dbName: String) =>
35-
val srcDir = new File(rootDir, dbName)
36-
val sdf = new SimpleDateFormat("yyyyMMdd'.'HHmmss")
37-
sdf.setTimeZone(TimeZone.getTimeZone("UTC"))
38-
val sdfNow = sdf.format(Calendar.getInstance().getTime())
39-
// move timestamp information in dbName to end of destination path
40-
// for example, from foo.1234567890 to foo.20170912.092828.deleted.1234567890
41-
val destPath = dbName.dropRight(10) + sdfNow + ".deleted." + dbName.takeRight(10)
42-
val destDir = new File(rootDir, destPath)
43-
logger.info("Renaming '%s' to '%s'".format(
44-
srcDir.getAbsolutePath, destDir.getAbsolutePath)
45-
)
46-
rename(srcDir, destDir)
4731
case CleanupDbMsg(dbName: String, activeSigs: List[String]) =>
4832
logger.info("Cleaning up " + dbName)
4933
val pattern = Pattern.compile("shards/[0-9a-f]+-[0-9a-f]+/" + dbName + "\\.[0-9]+/([0-9a-f]+)$")
@@ -78,14 +62,4 @@ class IndexCleanupService(ctx: ServiceContext[ConfigurationArgs]) extends Servic
7862
fileOrDir.delete
7963
}
8064

81-
private def rename(srcDir: File, destDir: File) {
82-
if (!srcDir.isDirectory) {
83-
return
84-
}
85-
if (!srcDir.renameTo(destDir)) {
86-
logger.error("Failed to rename directory from '%s' to '%s'".format(
87-
srcDir.getAbsolutePath, destDir.getAbsolutePath))
88-
}
89-
}
90-
9165
}

src/main/scala/com/cloudant/clouseau/IndexManagerService.scala

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,26 @@ class IndexManagerService(ctx: ServiceContext[ConfigurationArgs]) extends Servic
136136
case CloseLRUByPathMsg(path: String) =>
137137
lru.closeByPath(path)
138138
'ok
139+
case SoftDeleteMsg(path: String) =>
140+
lru.get(path) match {
141+
case null =>
142+
val manager = self
143+
node.spawn((_) => {
144+
openTimer.time {
145+
IndexService.start(node, ctx.args.config, path, "standard") match {
146+
case ('ok, pid: Pid) =>
147+
pid ! 'soft_delete
148+
'ok
149+
case error =>
150+
'error
151+
}
152+
}
153+
})
154+
case pid =>
155+
lru.remove(pid)
156+
pid ! 'soft_delete
157+
'ok
158+
}
139159
case 'version =>
140160
('ok, getClass.getPackage.getImplementationVersion)
141161
}

src/main/scala/com/cloudant/clouseau/IndexService.scala

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ import scalang.Reference
5757
import com.spatial4j.core.context.SpatialContext
5858
import com.spatial4j.core.distance.DistanceUtils
5959
import java.util.HashSet
60+
import java.util.Calendar
61+
import java.util.TimeZone
62+
import java.text.SimpleDateFormat
6063

6164
case class IndexServiceArgs(config: Configuration, name: String, queryParser: QueryParser, writer: IndexWriter)
6265
case class HighlightParameters(highlighter: Highlighter, highlightFields: List[String], highlightNumber: Int, analyzers: List[Analyzer])
@@ -178,6 +181,11 @@ class IndexService(ctx: ServiceContext[IndexServiceArgs]) extends Service(ctx) w
178181
dir.deleteFile(name)
179182
}
180183
exit('deleted)
184+
case 'soft_delete =>
185+
val dir = ctx.args.writer.getDirectory
186+
ctx.args.writer.close()
187+
softDelete(ctx.args.name)
188+
exit('soft_deleted)
181189
case 'maybe_commit =>
182190
commit(pendingSeq, pendingPurgeSeq)
183191
case ('committed, newUpdateSeq: Long, newPurgeSeq: Long) =>
@@ -220,14 +228,38 @@ class IndexService(ctx: ServiceContext[IndexServiceArgs]) extends Service(ctx) w
220228
ctx.args.writer.rollback()
221229
} catch {
222230
case e: AlreadyClosedException => 'ignored
223-
case e: IOException =>
224-
warn("Error while closing writer", e)
225-
ctx.args.writer.close()
231+
case e: IOException => warn("Error while closing writer", e)
226232
} finally {
227233
super.exit(msg)
228234
}
229235
}
230236

237+
private def softDelete(dbName: String) {
238+
val rootDir = new File(ctx.args.config.getString("clouseau.dir", "target/indexes"))
239+
val srcDir = new File(rootDir, dbName)
240+
val sdf = new SimpleDateFormat("yyyyMMdd'.'HHmmss")
241+
sdf.setTimeZone(TimeZone.getTimeZone("UTC"))
242+
val sdfNow = sdf.format(Calendar.getInstance().getTime())
243+
// move timestamp information in dbName to end of destination path
244+
// for example, from foo.1234567890 to foo.20170912.092828.deleted.1234567890
245+
val destPath = dbName.dropRight(10) + sdfNow + ".deleted." + dbName.takeRight(10)
246+
val destDir = new File(rootDir, destPath)
247+
rename(srcDir, destDir)
248+
}
249+
250+
private def rename(srcDir: File, destDir: File) {
251+
info("Renaming '%s' to '%s'".format(
252+
srcDir.getAbsolutePath, destDir.getAbsolutePath)
253+
)
254+
if (!srcDir.isDirectory) {
255+
return
256+
}
257+
if (!srcDir.renameTo(destDir)) {
258+
warn("Failed to rename directory from '%s' to '%s'".format(
259+
srcDir.getAbsolutePath, destDir.getAbsolutePath))
260+
}
261+
}
262+
231263
private def commit(newUpdateSeq: Long, newPurgeSeq: Long) {
232264
if (!committing && (newUpdateSeq > updateSeq || newPurgeSeq > purgeSeq)) {
233265
committing = true

src/test/scala/com/cloudant/clouseau/IndexCleanupServiceSpec.scala

Lines changed: 0 additions & 59 deletions
This file was deleted.

src/test/scala/com/cloudant/clouseau/IndexManagerServiceSpec.scala

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,22 @@ class IndexManagerServiceSpec extends SpecificationWithJUnit {
5555

5656
}
5757

58+
"the index soft deletion service" should {
59+
60+
"softly delete index when database is deleted" in new manager_service {
61+
node.call(service, SoftDeleteMsg("foo.5432109876"))
62+
Thread.sleep(1000)
63+
val indexdir = new File("target", "indexes")
64+
var subdirlist = List[String]()
65+
66+
for (file <- indexdir.listFiles if file.getName contains ".deleted") {
67+
subdirlist = file.getName() +: subdirlist
68+
}
69+
subdirlist.length > 0 must be equalTo true
70+
}
71+
72+
}
73+
5874
}
5975

6076
trait manager_service extends RunningNode {
@@ -90,4 +106,8 @@ trait manager_service extends RunningNode {
90106
foo2indexdir.mkdirs
91107
}
92108

109+
val foo3dir = new File(new File("target", "indexes"), "foo.5432109876")
110+
if (!foo3dir.exists) {
111+
foo3dir.mkdirs
112+
}
93113
}

0 commit comments

Comments
 (0)