mirror of
				https://github.com/superseriousbusiness/gotosocial.git
				synced 2025-11-03 21:32:24 -06:00 
			
		
		
		
	
		
			
				
	
	
		
			100 lines
		
	
	
	
		
			2.2 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			100 lines
		
	
	
	
		
			2.2 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
// Package memdb implements the "memdb" SQLite VFS.
 | 
						|
//
 | 
						|
// The "memdb" [vfs.VFS] allows the same in-memory database to be shared
 | 
						|
// among multiple database connections in the same process,
 | 
						|
// as long as the database name begins with "/".
 | 
						|
//
 | 
						|
// Importing package memdb registers the VFS:
 | 
						|
//
 | 
						|
//	import _ "github.com/ncruces/go-sqlite3/vfs/memdb"
 | 
						|
package memdb
 | 
						|
 | 
						|
import (
 | 
						|
	"fmt"
 | 
						|
	"net/url"
 | 
						|
	"sync"
 | 
						|
	"testing"
 | 
						|
 | 
						|
	"github.com/ncruces/go-sqlite3/vfs"
 | 
						|
)
 | 
						|
 | 
						|
func init() {
 | 
						|
	vfs.Register("memdb", memVFS{})
 | 
						|
}
 | 
						|
 | 
						|
var (
 | 
						|
	memoryMtx sync.Mutex
 | 
						|
	// +checklocks:memoryMtx
 | 
						|
	memoryDBs = map[string]*memDB{}
 | 
						|
)
 | 
						|
 | 
						|
// Create creates a shared memory database,
 | 
						|
// using data as its initial contents.
 | 
						|
// The new database takes ownership of data,
 | 
						|
// and the caller should not use data after this call.
 | 
						|
func Create(name string, data []byte) {
 | 
						|
	memoryMtx.Lock()
 | 
						|
	defer memoryMtx.Unlock()
 | 
						|
 | 
						|
	db := &memDB{
 | 
						|
		refs: 1,
 | 
						|
		name: name,
 | 
						|
		size: int64(len(data)),
 | 
						|
	}
 | 
						|
 | 
						|
	// Convert data from WAL/2 to rollback journal.
 | 
						|
	if len(data) >= 20 && (false ||
 | 
						|
		data[18] == 2 && data[19] == 2 ||
 | 
						|
		data[18] == 3 && data[19] == 3) {
 | 
						|
		data[18] = 1
 | 
						|
		data[19] = 1
 | 
						|
	}
 | 
						|
 | 
						|
	sectors := divRoundUp(db.size, sectorSize)
 | 
						|
	db.data = make([]*[sectorSize]byte, sectors)
 | 
						|
	for i := range db.data {
 | 
						|
		sector := data[i*sectorSize:]
 | 
						|
		if len(sector) >= sectorSize {
 | 
						|
			db.data[i] = (*[sectorSize]byte)(sector)
 | 
						|
		} else {
 | 
						|
			db.data[i] = new([sectorSize]byte)
 | 
						|
			copy((*db.data[i])[:], sector)
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	memoryDBs[name] = db
 | 
						|
}
 | 
						|
 | 
						|
// Delete deletes a shared memory database.
 | 
						|
func Delete(name string) {
 | 
						|
	memoryMtx.Lock()
 | 
						|
	defer memoryMtx.Unlock()
 | 
						|
	delete(memoryDBs, name)
 | 
						|
}
 | 
						|
 | 
						|
// TestDB creates an empty shared memory database for the test to use.
 | 
						|
// The database is automatically deleted when the test and all its subtests complete.
 | 
						|
// Each subsequent call to TestDB returns a unique database.
 | 
						|
func TestDB(tb testing.TB, params ...url.Values) string {
 | 
						|
	tb.Helper()
 | 
						|
 | 
						|
	name := fmt.Sprintf("%s_%p", tb.Name(), tb)
 | 
						|
	tb.Cleanup(func() { Delete(name) })
 | 
						|
	Create(name, nil)
 | 
						|
 | 
						|
	p := url.Values{"vfs": {"memdb"}}
 | 
						|
	for _, v := range params {
 | 
						|
		for k, v := range v {
 | 
						|
			for _, v := range v {
 | 
						|
				p.Add(k, v)
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	return (&url.URL{
 | 
						|
		Scheme:   "file",
 | 
						|
		OmitHost: true,
 | 
						|
		Path:     "/" + name,
 | 
						|
		RawQuery: p.Encode(),
 | 
						|
	}).String()
 | 
						|
}
 |