123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158 |
- package quota
- /*
- ArOZ Online Storage Quota Limiting and Tracking Module
- author: tobychui
- This system track and limit the quota of the users.
- */
- import (
- //"log"
- "os"
- "path/filepath"
- db "imuslab.com/arozos/mod/database"
- fs "imuslab.com/arozos/mod/filesystem"
- )
- //QuotaHandler Object
- type QuotaHandler struct {
- database *db.Database //System database for storing data
- username string //The current username for this handler
- fspool []*fs.FileSystemHandler
- TotalStorageQuota int64
- UsedStorageQuota int64
- }
- //Create a storage quotation handler for this user
- func NewUserQuotaHandler(database *db.Database, username string, fsh []*fs.FileSystemHandler, defaultQuota int64) *QuotaHandler {
- //Create the quota table if not exists
- totalQuota := defaultQuota //Use defalt quota if init first time
- err := database.NewTable("quota")
- if err != nil {
- //Set this account to readonly.
- return &QuotaHandler{
- database: database,
- username: username,
- fspool: fsh,
- TotalStorageQuota: 0,
- UsedStorageQuota: 0,
- }
- }
- //Get the user storage quota
- if !database.KeyExists("quota", username+"/quota") {
- //This user do not have a quota yet. Put in a default quota
- database.Write("quota", username+"/quota", defaultQuota)
- }
- //Load the user storage quota from database
- thisUserQuotaManager := QuotaHandler{
- database: database,
- username: username,
- fspool: fsh,
- TotalStorageQuota: totalQuota,
- UsedStorageQuota: 0,
- }
- thisUserQuotaManager.CalculateQuotaUsage()
- return &thisUserQuotaManager
- }
- //Set and Get the user storage quota
- func (q *QuotaHandler) SetUserStorageQuota(quota int64) {
- q.database.Write("quota", q.username+"/quota", quota)
- q.TotalStorageQuota = quota
- }
- func (q *QuotaHandler) GetUserStorageQuota() int64 {
- quota := int64(-2)
- q.database.Read("quota", q.username+"/quota", "a)
- //Also update the one in memory
- q.TotalStorageQuota = quota
- return quota
- }
- //Check if the user's quota has been initialized
- func (q *QuotaHandler) IsQuotaInitialized() bool {
- if q.GetUserStorageQuota() == int64(-2) {
- return false
- } else {
- return true
- }
- }
- func (q *QuotaHandler) RemoveUserQuota() {
- q.database.Delete("quota", q.username+"/quota")
- }
- func (q *QuotaHandler) HaveSpace(size int64) bool {
- remaining := q.TotalStorageQuota - q.UsedStorageQuota
- if q.TotalStorageQuota == -1 {
- return true
- }
- if size < remaining {
- return true
- } else {
- return false
- }
- }
- //Update the user's storage pool to new one
- func (q *QuotaHandler) UpdateUserStoragePool(fsh []*fs.FileSystemHandler) {
- q.fspool = fsh
- }
- //Claim a space for the given file and set the file ownership to this user
- func (q *QuotaHandler) AllocateSpace(filesize int64) error {
- q.UsedStorageQuota += filesize
- return nil
- }
- //Reclaim file occupied space (Call this before removing it)
- func (q *QuotaHandler) ReclaimSpace(filesize int64) error {
- q.UsedStorageQuota -= filesize
- if q.UsedStorageQuota < 0 {
- q.UsedStorageQuota = 0
- }
- return nil
- }
- //Recalculate the user storage quota. This takes a lot of time and CPUs
- func (q *QuotaHandler) CalculateQuotaUsage() {
- totalUsedVolume := int64(0)
- for _, thisfs := range q.fspool {
- if thisfs.Hierarchy == "user" {
- if !fs.FileExists(filepath.ToSlash(filepath.Clean(thisfs.Path)) + "/users/" + q.username) {
- //This folder not exists. Maybe not initialized
- continue
- }
- err := filepath.Walk(filepath.ToSlash(filepath.Clean(thisfs.Path))+"/users/"+q.username, func(path string, info os.FileInfo, err error) error {
- if info == nil || err != nil {
- //This file gone when quota is calculating. Ignore this
- return nil
- }
- if !info.IsDir() {
- totalUsedVolume += fs.GetFileSize(path)
- }
- return nil
- })
- if err != nil {
- continue
- }
- }
- }
- q.UsedStorageQuota = totalUsedVolume
- }
- func inSlice(slice []string, val string) (int, bool) {
- for i, item := range slice {
- if item == val {
- return i, true
- }
- }
- return -1, false
- }
|