github.com/mgulsoy/arnedb@v1.2.2-alpha/arnedb.go (about)

     1  // Package arnedb implements database access layer. Using this package one can embed a simple
     2  // database functionality into his/her application. Arnedb is not a high performance database.
     3  // There are a lot of database products which can achieve high performance. Arnedb provides a
     4  // lightweight database implementation which is embeddable in any GO app. Design goals of Arnedb
     5  // are:
     6  // * Low memory usage: Can be run in resource constrained environments
     7  // * Simplicity: Hence the title implies
     8  // * Text file storage: All the data is stored in text based JSON files
     9  package arnedb
    10  
    11  import (
    12  	"errors"
    13  	"fmt"
    14  	"io/ioutil"
    15  	"os"
    16  	"path/filepath"
    17  )
    18  
    19  // Coll represents a single collection of documents. There is no limit for collections
    20  type Coll struct {
    21  	dbpath string // Kolleksiyon klasörünün yolu.
    22  	// Name is the collection name.
    23  	Name string
    24  }
    25  
    26  // ArneDB represents a single database. There is no limit for databases. (Unless you have enough disk space)
    27  type ArneDB struct {
    28  	// Name is the database name
    29  	Name    string
    30  	baseDir string           // Veritabanı ana klasörü,
    31  	path    string           // Veritabanı tam yolu
    32  	colls   map[string]*Coll // içindeki Coll'lar (Kolleksiyonlar)
    33  }
    34  
    35  // Open function opens an existing or creates a new database.
    36  func Open(baseDir, dbName string) (*ArneDB, error) {
    37  
    38  	// baseDir var mı? Yoksa oluştur.
    39  	// TODO: Error tipi oluşturulabilir. Şimdilik sadece metin errorları kullanılır
    40  	bfi, err := os.Stat(baseDir)
    41  	if os.IsNotExist(err) {
    42  		return nil, errors.New(fmt.Sprintf("Basedir does not exist! : %s", err.Error())) //hata, ana klasör yok
    43  	}
    44  
    45  	if !bfi.Mode().IsDir() {
    46  		// ana klasör aslında klasör değil
    47  		return nil, errors.New("base dir is not a dir")
    48  	}
    49  
    50  	// Ana klasör var, Şimdi veritabanına bakacağız.
    51  	dbPath := filepath.Join(baseDir, dbName)
    52  	dbfi, err := os.Stat(dbPath)
    53  	if os.IsNotExist(err) {
    54  		//Eğer yoksa oluştur
    55  		err = os.Mkdir(dbPath, 0700)
    56  		if err != nil {
    57  			// oluşturulamıyor!
    58  			return nil, err
    59  		}
    60  	} else {
    61  		//Aynı adlı dosya olabillir.
    62  		if !dbfi.Mode().IsDir() {
    63  			// Bir klasör değil!
    64  			return nil, errors.New("a file exists with the same name")
    65  		}
    66  	}
    67  
    68  	//Kontroller tamam db hazır
    69  	var db = ArneDB{
    70  		baseDir,
    71  		dbName,
    72  		dbPath,
    73  		make(map[string]*Coll),
    74  	}
    75  
    76  	// TODO: Veritabanı compact işlemleri yapılması
    77  
    78  	// Şimdi (coll) kolleksiyonlar yüklenir.
    79  	files, err := ioutil.ReadDir(dbPath)
    80  	if err != nil {
    81  		return nil, errors.New("cannot read db collections")
    82  	}
    83  
    84  	for _, finfo := range files {
    85  		if finfo.IsDir() {
    86  			// Bu bizim ilgilendiğimiz kolleksiyondur
    87  			var c = Coll{
    88  				Name:   finfo.Name(),
    89  				dbpath: filepath.Join(dbPath, finfo.Name()),
    90  			}
    91  			db.colls[c.Name] = &c
    92  		}
    93  		// dosyalar ile ilgilenmeyiz!
    94  	}
    95  
    96  	// klasörlerin her biri bizim kolleksiyonumuzdur.
    97  
    98  	return &db, nil // hatasız dönüş
    99  }
   100  
   101  // TODO: Export işlemi : Zip dosyası olarak export edilir.
   102  // TODO: Import işlemi : Zip dosyası import edilir.
   103  
   104  // Herhangi bir şeyi bellekte tutmadığımız için Close gibi bir işleme ihtiyacımız yok.
   105  
   106  // Collection İşlemleri ---------------------------------------------------------------
   107  
   108  // CreateColl function creates a collection and returns it.
   109  func (db *ArneDB) CreateColl(collName string) (*Coll, error) {
   110  	// Oluşturulmak istenen collection var mı ona bakarız.
   111  	collPath := filepath.Join(db.path, collName)
   112  	_, err := os.Stat(collPath)
   113  
   114  	if os.IsExist(err) {
   115  		return nil, errors.New(fmt.Sprintf("a dir name exists with the same name: %s -> %s", collName, err.Error()))
   116  	}
   117  
   118  	// Klasör yok demektir.
   119  	err = os.Mkdir(collPath, 0700)
   120  	if err != nil {
   121  		return nil, err
   122  	} // klasörü oluşturamadı
   123  
   124  	var c = Coll{
   125  		Name:   collName,
   126  		dbpath: collPath,
   127  	}
   128  	db.colls[c.Name] = &c
   129  
   130  	return &c, nil
   131  }
   132  
   133  // DeleteColl function deletes a given collection.
   134  func (db *ArneDB) DeleteColl(collName string) error {
   135  	collObj, keyFound := db.colls[collName]
   136  	if !keyFound {
   137  		return errors.New("collection does not exist")
   138  	}
   139  
   140  	err := os.RemoveAll(collObj.dbpath)
   141  	if err == nil { // file system removal success
   142  		delete(db.colls, collName)
   143  	}
   144  
   145  	// işlem başarılı
   146  	return err
   147  }
   148  
   149  // GetColl gets the collection by the given name. It returns the pointer if it finds a collection
   150  // with the given name. If not it returns nil
   151  func (db *ArneDB) GetColl(collName string) *Coll {
   152  
   153  	if len(db.colls) == 0 {
   154  		return nil // Return nil if there is no collection
   155  	}
   156  
   157  	c, keyExists := db.colls[collName]
   158  	if !keyExists {
   159  		return nil
   160  	}
   161  
   162  	return c
   163  }
   164  
   165  // GelCollNames returns all present collection names as []string
   166  func (db *ArneDB) GelCollNames() (result []string) {
   167  	if len(db.colls) == 0 {
   168  		return nil // Return nil if there is no collection
   169  	}
   170  
   171  	result = make([]string, len(db.colls))
   172  	i := 0
   173  	for k := range db.colls {
   174  		result[i] = k
   175  		i++
   176  	}
   177  
   178  	return result
   179  }