File: TextFileStorage.xotcl

package info (click to toggle)
xotcl 0.85.3-3
  • links: PTS
  • area: main
  • in suites: woody
  • size: 2,832 kB
  • ctags: 2,734
  • sloc: ansic: 18,065; tcl: 1,256; makefile: 653; sh: 430
file content (150 lines) | stat: -rw-r--r-- 4,028 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
package provide xotcl::store::textfile 0.84
package require xotcl::store

Class Storage=TextFile -superclass Storage -parameter {
  filename
  reorgCounter
  reorgMaxValue
}

Storage=TextFile instproc init args {
  [self] instvar reorgCounter reorgMaxValue searchID
  ::set reorgCounter 0
  ::set reorgMaxValue 1000
  ::set searchID ""
  next
}
Storage=TextFile instproc reorganizeDB {} {
  [self] instvar noreorg reorgCounter reorgMaxValue filename keys
  ::set reorgCounter -1
  #puts "***reorganizeDB"
  if {[::info exists filename]} {
    ::set noreorg 1
    ::array set bkeys [::array get keys]
    ::array set keys {}
    #    parray bkeys

    ::set bak $filename.orig
    file rename -force $filename $bak
    foreach k [::array names bkeys] {
      ::set bf [::open $bak r]
      seek $bf [lindex $bkeys($k) 0]
      ::set c [read $bf [lindex $bkeys($k) 1]]
      ::close $bf
      #puts "***STORING $k [lindex $c 1]"
      [self] set $k [lindex $c 1]
    }
    file delete -force $bak
    ::unset noreorg
  }
}
Storage=TextFile instproc open fn {
  [self] instvar keys filename
  ::array set keys {}
  ::set position 0
  ::set filename $fn
  if {[file exists $filename]} {
    ::set f [::open $filename r]
    ::set c [read $f]
    ::close $f
    
    ::set positions ""
    foreach {k v} $c {
      ::incr position [string first $k [string range $c $position end]]
      ::set filepos $position
      #puts "+++ '[string index $c [expr $filepos - 1]]' pos=$position"
      while {[string index $c [expr {$filepos - 1}]] == "\{"} {
	incr filepos -1
      }
      if {[::info exists keys($k)]} {
	# no clean close
	puts "Storage Open -- key duplicated in $filename: $k"
      }
      ::set keys($k) $filepos
      if {[info exists lastKey]} {
	lappend keys($lastKey) [expr {$filepos - $keys($lastKey)}]
      }
      ::set lastKey $k
      ::incr position 2
    }
    if {[info exists lastKey]} {
      lappend keys($lastKey) [expr {[string length $c] -  $filepos}]
    }
  }
#  parray keys
}
Storage=TextFile instproc exists key {
  [self] instvar keys
  ::info exists keys($key)
}

Storage=TextFile instproc set args {
  [self] instvar keys noreorg reorgCounter reorgMaxValue filename
  ::set key [lindex $args 0]
  ::set l [llength $args]
  if {$l == 1} {     ;# fetch
    if {[::info exists keys($key)]} {
      ::set f [::open $filename r]
      #puts "***fetch -- $keys($key)"
      seek $f [lindex $keys($key) 0]
      ::set c [read $f [lindex $keys($key) 1]]
      ::close $f
      return [lindex $c 1]
    } else {
      error "no such variable '$key'"    
    }
  } elseif {$l == 2} {    ;# store
    if {![::info exists noreorg] && [::info exists keys($key)]} {
      ::incr reorgCounter    
    }
    ::set f [::open $filename a+]
    ::set position [tell $f]
    #puts "***store -- putting [::list $key [lindex $args 1]] at $position"
    ::set c [::list $key [lindex $args 1]]
    puts $f $c
    ::close $f
    ::set keys($key) [::list $position [expr {[string length $c] + 1}]]
    #  parray keys
    if {$reorgCounter > $reorgMaxValue} {
      [self] reorganizeDB    
    }
  } else { next }
}

Storage=TextFile instproc names  {} {
  ::array names [self]::keys
}
Storage=TextFile instproc close {} {
  [self] instvar filename keys
  [self] reorganizeDB
  ::unset filename
  ::unset keys
}
Storage=TextFile instproc unset key {
  [self] instvar keys
  if {[::info exists keys($key)]} {
    ::unset keys($key)
  }
  [self] reorganizeDB
}

Storage=TextFile instproc firstkey {} {
  [self] instvar keys searchID
  if {$searchID != ""} {
    array donesearch keys $searchID
  }
  ::set searchID [array startsearch keys]
  return [array nextelement keys $searchID]
}
Storage=TextFile instproc nextkey {} {
  [self] instvar keys searchID
  if {$searchID == ""} {
    error "[self class]: firstkey was not invoked on storage search"
  }
  ::set elt [array nextelement keys $searchID]
  if {$elt == ""} {
    # if array end is reach search is terminated automatically!!
    ::set searchID ""
  }
  return $elt
}