Skip to content

Commit 1ce57e4

Browse files
tcnichollmarinimax-zillarobkooper
authored
199 show space bytes (#263)
* adding parameter spaceBytes inside getSpace * add method getBytesPerSpace changing html * adding to space statistics need cleanup * statistics changed - replaced with more data modeled on the index page We now see Collections, Datasets, Files, Bytes per space and Users in right column * changelog * adding spaceBytes parameter, does not work yet * new method, get bytes for dataset * methods need to match * adding and removing datasets from space will increment spaceBytes. * increment bytes when file added to dataset * decrement space bytes on remove file * remove commented out code * use cached value of bytes per space not method call * adding update space bytes method * added space bytes update * fixig test * fix few issues with migration - no datasets in space would result in not writing out count - very large databsae would have cursor timeout - simplified logic to count bytes * Space layout with statistics (#283) * make space layout more like datasets/files * update changelog - undo removal - add comment + link to issue for space stats - comment about new layout * Lowered margin from 20px to 15px for button links. Co-authored-by: Luigi Marini <[email protected]> Co-authored-by: Luigi Marini <[email protected]> Co-authored-by: Max Burnette <[email protected]> Co-authored-by: Rob Kooper <[email protected]> Co-authored-by: Luigi Marini <[email protected]>
1 parent 5279445 commit 1ce57e4

File tree

17 files changed

+271
-156
lines changed

17 files changed

+271
-156
lines changed

CHANGELOG.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
1414
### Added
1515
- Adding mime type for geojson
1616
- Add "when" parameter in a few GET API endpoints to enable pagination [#266](https://github.com/clowder-framework/clowder/issues/266)
17+
- Show statistics of spaces (bytes, users. etc) [#119](https://github.com/clowder-framework/clowder/issues/119)
18+
19+
### Changed
1720
- Add "id" in GET metadata.jsonld endpoints [#278](https://github.com/clowder-framework/clowder/issues/278)
1821

1922
## 1.18.1 - 2021-08-16
@@ -71,7 +74,6 @@ If any files are returned, you should check to see if these files affected and a
7174

7275
### Changed
7376
- Updated Sphinx dependencies due to security and changes in required packages.
74-
7577
- Updated the three.js libraries for the FBX previewer
7678

7779
## 1.16.0 - 2021-03-31

app/api/Files.scala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1675,6 +1675,10 @@ class Files @Inject()(
16751675
// notify rabbitmq
16761676
datasets.findByFileIdAllContain(file.id).foreach { ds =>
16771677
routing.fileRemovedFromDataset(file, ds, Utils.baseUrl(request), request.apiKey)
1678+
val ds_spaces = ds.spaces
1679+
for (ds_s <- ds_spaces) {
1680+
spaces.decrementSpaceBytes(ds_s, file.length)
1681+
}
16781682
}
16791683

16801684
//this stmt has to be before files.removeFile

app/api/Spaces.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ class Spaces @Inject()(spaces: SpaceService,
4141
val userId = request.user.get.id
4242
val c = ProjectSpace(name = name, description = description, created = new Date(), creator = userId,
4343
homePage = List.empty, logoURL = None, bannerURL = None, collectionCount = 0,
44-
datasetCount = 0, userCount = 0, metadata = List.empty)
44+
datasetCount = 0, userCount = 0, spaceBytes = 0, metadata = List.empty)
4545
spaces.insert(c) match {
4646
case Some(id) => {
4747
appConfig.incrementCount('spaces, 1)

app/controllers/SecuredController.scala

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,11 @@ package controllers
22

33
import api.Permission.Permission
44
import api.{Permission, UserRequest}
5-
import models.{ClowderUser, RequestResource, ResourceRef, User, UserStatus}
6-
import org.apache.commons.lang.StringEscapeUtils._
5+
import models.{ClowderUser, ResourceRef, User, UserStatus}
76
import play.api.i18n.Messages
87
import play.api.mvc._
98
import securesocial.core.{Authenticator, SecureSocial, UserService}
109
import services._
11-
import securesocial.core.IdentityProvider
12-
import securesocial.core.providers.utils.RoutesHelper
1310

1411
import scala.concurrent.Future
1512

@@ -156,7 +153,7 @@ trait SecuredController extends Controller {
156153
val spaces: SpaceService = DI.injector.getInstance(classOf[SpaceService])
157154
spaces.get(id) match {
158155
case None => Future.successful(BadRequest(views.html.notFound(spaceTitle + " does not exist.")(user)))
159-
case Some(space) => Future.successful(Forbidden(views.html.spaces.space(space,List(),List(),List(),List(),"", Map(),List())(user)))
156+
case Some(space) => Future.successful(Forbidden(views.html.spaces.space(space,List(),List(),List(),List(),"", Map(),List(),0,0)(user)))
160157
}
161158
}
162159

app/controllers/Spaces.scala

Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,22 @@
11
package controllers
22

3-
import java.net.URL
4-
import java.util.{ Calendar, Date }
5-
import javax.inject.Inject
6-
73
import api.Permission
84
import api.Permission._
95
import models._
10-
import play.api.{ Logger, Play }
6+
import org.joda.time.DateTime
117
import play.api.data.Forms._
12-
import play.api.data.{ Form, Forms }
13-
import play.api.libs.json.JsValue
14-
import play.api.libs.json.Json
8+
import play.api.data.{Form, Forms}
159
import play.api.i18n.Messages
10+
import play.api.{Logger, Play}
11+
import securesocial.core.providers.{Token, UsernamePasswordProvider}
1612
import services._
17-
import securesocial.core.providers.{ Token, UsernamePasswordProvider }
18-
import org.joda.time.DateTime
19-
import play.api.i18n.Messages
20-
import play.api.libs.ws._
21-
import services.AppConfiguration
22-
import util.{ Formatters, Mail, Publications }
13+
import util.{Formatters, Mail, Publications}
2314

15+
import java.net.URL
16+
import java.util.{Calendar, Date}
17+
import javax.inject.Inject
2418
import scala.collection.immutable.List
25-
import scala.collection.mutable.{ ArrayBuffer, ListBuffer }
26-
import scala.concurrent.{ Future, Await }
27-
import scala.concurrent.duration._
28-
import org.apache.commons.lang.StringEscapeUtils.escapeJava
19+
import scala.collection.mutable.{ArrayBuffer, ListBuffer}
2920

3021
/**
3122
* Spaces allow users to partition the data into realms only accessible to users with the right permissions.
@@ -176,6 +167,8 @@ class Spaces @Inject() (spaces: SpaceService, users: UserService, events: EventS
176167
var creatorActual: User = null
177168
val collectionsInSpace = spaces.getCollectionsInSpace(Some(id.stringify), Some(size))
178169
val datasetsInSpace = datasets.listSpace(size, id.toString(), user)
170+
val spaceBytes : Long = s.spaceBytes
171+
val spaceFiles : Integer = getFilesPerSpace(id, user.get)
179172
val publicDatasetsInSpace = datasets.listSpaceStatus(size, id.toString(), "publicAll", user)
180173
val usersInSpace = spaces.getUsersInSpace(id, None)
181174
var curationObjectsInSpace: List[CurationObject] = List()
@@ -224,7 +217,7 @@ class Spaces @Inject() (spaces: SpaceService, users: UserService, events: EventS
224217
case None => List.empty
225218
}
226219
sinkService.logSpaceViewEvent(s, user)
227-
Ok(views.html.spaces.space(Utils.decodeSpaceElements(s), collectionsInSpace, publicDatasetsInSpace, datasetsInSpace, rs, play.Play.application().configuration().getString("SEADservices.uri"), userRoleMap, userSelections))
220+
Ok(views.html.spaces.space(Utils.decodeSpaceElements(s), collectionsInSpace, publicDatasetsInSpace, datasetsInSpace, rs, play.Play.application().configuration().getString("SEADservices.uri"), userRoleMap, userSelections, spaceBytes, spaceFiles))
228221
}
229222
case None => BadRequest(views.html.notFound(spaceTitle + " does not exist."))
230223
}
@@ -421,7 +414,7 @@ class Spaces @Inject() (spaces: SpaceService, users: UserService, events: EventS
421414
val newSpace = ProjectSpace(name = formData.name, description = formData.description,
422415
created = new Date, creator = userId, homePage = formData.homePage,
423416
logoURL = formData.logoURL, bannerURL = formData.bannerURL,
424-
collectionCount = 0, datasetCount = 0, userCount = 0, metadata = List.empty,
417+
collectionCount = 0, datasetCount = 0, userCount = 0, spaceBytes = 0, metadata = List.empty,
425418
resourceTimeToLive = formData.resourceTimeToLive * 60 * 60 * 1000L, isTimeToLiveEnabled = formData.isTimeToLiveEnabled,
426419
status = formData.access,
427420
affiliatedSpaces = formData.affSpace)
@@ -648,4 +641,14 @@ class Spaces @Inject() (spaces: SpaceService, users: UserService, events: EventS
648641
}
649642
}
650643

644+
private def getFilesPerSpace(spaceId: UUID, user: models.User) : Integer = {
645+
var spaceFiles: Integer = 0
646+
val allDatasetsInSpace = datasets.listSpace(0, spaceId.toString(), Some(user))
647+
for (ds <- allDatasetsInSpace) {
648+
val files_in_ds = ds.files.length
649+
spaceFiles += files_in_ds
650+
}
651+
spaceFiles
652+
}
653+
651654
}

app/models/Space.scala

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ case class ProjectSpace (
2323
collectionCount: Integer,
2424
datasetCount: Integer,
2525
userCount: Integer,
26+
spaceBytes: Long,
2627
metadata: List[Metadata],
2728
resourceTimeToLive: Long = SpaceConfig.getTimeToLive(),
2829
isTimeToLiveEnabled: Boolean = SpaceConfig.getIsTimeToLiveEnabled(),
@@ -52,7 +53,8 @@ case class UserSpace (
5253
bannerURL: Option[URL],
5354
collectionCount: Integer,
5455
datasetCount: Integer,
55-
userCount: Integer)
56+
userCount: Integer,
57+
spaceBytes: Long)
5658

5759
case class SpaceInvite(
5860
id: UUID = UUID.generate,

app/services/DatasetService.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,8 @@ trait DatasetService {
295295

296296
def findMetadataChangedDatasets(): List[Dataset]
297297

298+
def getBytesForDataset(datasetId: UUID) : Long
299+
298300
/**
299301
* Check recursively whether a dataset's user-input metadata match a requested search tree.
300302
*/

app/services/SpaceService.scala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,10 @@ trait SpaceService {
9494

9595
def incrementCollectionCounter(collection: UUID, space: UUID, increment: Int)
9696

97+
def incrementSpaceBytes(space: UUID, increment: Long)
98+
99+
def decrementSpaceBytes(space: UUID, decrement: Long)
100+
97101
def addDataset(dataset: UUID, space: UUID)
98102

99103
def removeDataset(dataset:UUID, space: UUID)

app/services/mongodb/MongoDBDatasetService.scala

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1068,6 +1068,17 @@ class MongoDBDatasetService @Inject() (
10681068
Dataset.find(MongoDBObject("userMetadataWasModified" -> true)).toList
10691069
}
10701070

1071+
def getBytesForDataset(datasetId: UUID) : Long = {
1072+
val dataset = Dataset.findOneById(new ObjectId(datasetId.stringify)).get
1073+
val datasetFiles = dataset.files
1074+
var datasetBytes : Long = 0
1075+
datasetFiles.foreach{ f => {
1076+
val currentFileBytes = files.get(f).get.length
1077+
datasetBytes += currentFileBytes
1078+
}}
1079+
datasetBytes
1080+
}
1081+
10711082
def removeTag(id: UUID, tagId: UUID) {
10721083
Logger.debug("Removing tag " + tagId)
10731084
val result = Dataset.update(MongoDBObject("_id" -> new ObjectId(id.stringify)), $pull("tags" -> MongoDBObject("_id" -> new ObjectId(tagId.stringify))), false, false, WriteConcern.Safe)

app/services/mongodb/MongoDBSpaceService.scala

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,14 @@ class MongoDBSpaceService @Inject() (
378378
ProjectSpaceDAO.update(MongoDBObject("_id" -> new ObjectId(space.stringify)), $inc("collectionCount" -> -1), upsert=false, multi=false, WriteConcern.Safe)
379379
}
380380

381+
def incrementSpaceBytes(space: UUID, increment: Long ): Unit = {
382+
ProjectSpaceDAO.update(MongoDBObject("_id" -> new ObjectId(space.stringify)), $inc("spaceBytes" -> increment), upsert=false, multi=false, WriteConcern.Safe)
383+
}
384+
385+
def decrementSpaceBytes(space: UUID, decrement: Long): Unit = {
386+
ProjectSpaceDAO.update(MongoDBObject("_id" -> new ObjectId(space.stringify)), $inc("spaceBytes" -> decrement), upsert=false, multi=false, WriteConcern.Safe)
387+
}
388+
381389
def removeCollection(collection:UUID, space:UUID): Unit = {
382390
log.debug(s"Space Service - removing $collection from $space")
383391
collections.removeFromSpace(collection, space)
@@ -390,7 +398,9 @@ class MongoDBSpaceService @Inject() (
390398
*/
391399
def addDataset(dataset: UUID, space: UUID): Unit = {
392400
log.debug(s"Space Service - Adding $dataset to $space")
401+
val datasetBytes = datasets.getBytesForDataset(dataset)
393402
datasets.addToSpace(dataset, space)
403+
ProjectSpaceDAO.update(MongoDBObject("_id" -> new ObjectId(space.stringify)), $inc("spaceBytes" -> datasetBytes), upsert=false, multi=false, WriteConcern.Safe)
394404
ProjectSpaceDAO.update(MongoDBObject("_id" -> new ObjectId(space.stringify)), $inc("datasetCount" -> 1), upsert=false, multi=false, WriteConcern.Safe)
395405

396406
}
@@ -404,6 +414,8 @@ class MongoDBSpaceService @Inject() (
404414
def removeDataset(dataset:UUID, space:UUID): Unit = {
405415
log.debug(s"Space Service - removing $dataset from $space")
406416
datasets.removeFromSpace(dataset, space)
417+
val datasetBytes = datasets.getBytesForDataset(dataset)
418+
ProjectSpaceDAO.update(MongoDBObject("_id" -> new ObjectId(space.stringify)), $inc("spaceBytes" -> -datasetBytes), upsert=false, multi=false, WriteConcern.Safe)
407419
ProjectSpaceDAO.update(MongoDBObject("_id" -> new ObjectId(space.stringify)), $inc("datasetCount" -> -1), upsert=false, multi=false, WriteConcern.Safe)
408420
}
409421

0 commit comments

Comments
 (0)