| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154 | 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 Objecttype 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 userfunc 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 quotafunc (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 initializedfunc (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 onefunc (q *QuotaHandler) UpdateUserStoragePool(fsh []*fs.FileSystemHandler) {	q.fspool = fsh}//Claim a space for the given file and set the file ownership to this userfunc (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 CPUsfunc (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.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}
 |