1 # This class is used to keep track of a typeid => class name
2 # mapping in the database. You create a new typemap object and
3 # describe the table to it (tablename, class field name, id field name)
4 # You can then look up class->typeid or vice-versa on the Typemap object
5 # Mischa Spiegelmock, 4/21/06
16 # table is the typemap table
17 # the fields are the names of the fields in the table
19 my ($class, %opts) = @_;
21 my $table = delete $opts{table
} or croak
"No table";
22 my $classfield = delete $opts{classfield
} or croak
"No class field";
23 my $idfield = delete $opts{idfield
} or croak
"No id field";
25 croak
"Extra args passed to LJ::Typemap->new" if %opts;
27 return $singletons{$table} if $singletons{$table};
29 croak
"Invalid arguments passed to LJ::Typemap->new"
30 unless ($class && $table !~ /\W/g && $idfield !~/\W/g && $classfield !~/\W/g);
35 classfield
=> $classfield,
40 return $singletons{$table} = bless $self, $class;
44 # errors hard if you look up a typeid that isn't mapped
46 my ($self, $typeid) = @_;
48 $self->_load unless $self->{loaded
};
49 my $proc_cache = $self->{cache
};
51 my ($class) = grep { $proc_cache->{$_} == $typeid } keys %$proc_cache;
53 croak
"No class for id $typeid on table $self->{table}" unless $class;
58 # this will return the typeid of a given class.
59 # if there is no typeid for this class, it will create one.
60 # returns undef on failure
62 my ($self, $class) = @_;
64 croak
"No class specified in class_to_typeid" unless $class;
66 $self->_load unless $self->{loaded
};
67 my $proc_cache = $self->{cache
};
68 my $classid = $proc_cache->{$class};
69 return $classid if defined $classid;
71 # this class does not have a typeid. create one.
72 my $dbh = LJ
::get_db_writer
();
74 my $table = $self->{table
} or croak
"No table";
75 my $classfield = $self->{classfield
} or croak
"No class field";
76 my $idfield = $self->{idfield
} or croak
"No id field";
79 $dbh->do("INSERT INTO $table ($classfield) VALUES (?)",
83 # inserted fine, get ID
84 $classid = $dbh->{'mysql_insertid'};
86 # race condition, try to select again
87 $classid = $dbh->selectrow_array("SELECT $idfield FROM $table WHERE $classfield = ?",
89 or die "Typemap could not generate ID after race condition";
92 # we had better have a classid by now... big trouble if we don't
93 die "Could not create typeid for table $table class $class" unless $classid;
96 $proc_cache->{$class} = $classid;
98 $self->proc_cache_to_memcache;
103 # given a list of classes, create an ID for each if no ID exists
104 # returns list of corresponding IDs
106 my ($self, @classes) = @_;
112 foreach my $class (@classes) {
113 # just ask for the typeid of this class
114 push @ids, $self->class_to_typeid($class);
120 # delete a class->id map
121 # returns not undef on success
123 my ($self, $class) = @_;
125 my $dbh = LJ
::get_db_writer
() or die "No DB writer";
127 my $table = $self->{table
} or die "No table";
128 my $classfield = $self->{classfield
} or return undef;
130 $dbh->do("DELETE FROM $table WHERE $classfield=?", undef, $class) or return undef;
132 delete $self->{cache
}->{$class};
133 $self->proc_cache_to_memcache;
138 # save the process cache to memcache
139 sub proc_cache_to_memcache
{
141 my $table = $self->{table
};
143 LJ
::MemCache
::set
("typemap_$table", $self->{cache
}, 120);
146 # returns an array of all of the classes in the table
151 return keys %{$self->{cache
}};
154 # makes sure typemap cache is loaded
160 my $table = $self->{table
} or die "No table";
161 my $classfield = $self->{classfield
} or die "No class field";
162 my $idfield = $self->{idfield
} or die "No id field";
164 my $proc_cache = $self->{cache
};
167 my $memcached_typemap = LJ
::MemCache
::get
("typemap_$table");
168 if ($memcached_typemap) {
170 $proc_cache = $memcached_typemap;
173 my $dbr = LJ
::get_db_reader
();
174 return undef unless $dbr;
176 # load typemap from DB
177 my $sth = $dbr->prepare("SELECT $classfield, $idfield FROM $table");
178 die $dbr->errstr if $dbr->errstr;
179 return undef unless $sth;
182 die $dbr->errstr if $dbr->errstr;
184 while (my $idmap = $sth->fetchrow_hashref) {
185 $proc_cache->{$idmap->{$classfield}} = $idmap->{$idfield};
189 $self->proc_cache_to_memcache;
191 $self->{cache
} = $proc_cache;