mirror of
				https://github.com/superseriousbusiness/gotosocial.git
				synced 2025-10-31 02:12:24 -05:00 
			
		
		
		
	
		
			
				
	
	
		
			99 lines
		
	
	
	
		
			2.2 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			99 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 && (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()
 | |
| }
 |