~ubuntu-branches/debian/squeeze/erlang/squeeze

« back to all changes in this revision

Viewing changes to lib/snmp/src/agent/snmpa_general_db.erl

  • Committer: Bazaar Package Importer
  • Author(s): Erlang Packagers, Sergei Golovan
  • Date: 2006-12-03 17:07:44 UTC
  • mfrom: (2.1.11 feisty)
  • Revision ID: james.westby@ubuntu.com-20061203170744-rghjwupacqlzs6kv
Tags: 1:11.b.2-4
[ Sergei Golovan ]
Fixed erlang-base and erlang-base-hipe prerm scripts.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
%% ``The contents of this file are subject to the Erlang Public License,
 
2
%% Version 1.1, (the "License"); you may not use this file except in
 
3
%% compliance with the License. You should have received a copy of the
 
4
%% Erlang Public License along with this software. If not, it can be
 
5
%% retrieved via the world wide web at http://www.erlang.org/.
 
6
%% 
 
7
%% Software distributed under the License is distributed on an "AS IS"
 
8
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
 
9
%% the License for the specific language governing rights and limitations
 
10
%% under the License.
 
11
%% 
 
12
%% The Initial Developer of the Original Code is Ericsson Utvecklings AB.
 
13
%% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
 
14
%% AB. All Rights Reserved.''
 
15
%% 
 
16
%%     $Id$
 
17
%%
 
18
-module(snmpa_general_db).
 
19
 
 
20
 
 
21
%%%-----------------------------------------------------------------
 
22
%%% This module implements a very simple "generic" MIB database 
 
23
%%% interface. It contains the most common functions performed.
 
24
%%% It is generic in the sense that it implements both an interface
 
25
%%% to mnesia and ets.
 
26
%%%
 
27
%%% Note that this module has nothing to do with the snmp_generic
 
28
%%% and snmp_generic_mnesia modules.
 
29
%%%-----------------------------------------------------------------
 
30
 
 
31
-export([open/5, close/1, read/2, write/2, delete/1, delete/2]).
 
32
-export([sync/1, backup/2]).
 
33
-export([match_object/2, match_delete/2]).
 
34
-export([tab2list/1, info/1, info/2]).
 
35
 
 
36
 
 
37
-define(VMODULE,"GDB").
 
38
-include("snmp_verbosity.hrl").
 
39
 
 
40
 
 
41
%% ---------------------------------------------------------------
 
42
%% open(Info,Name,RecName,Attr,Type) -> term()
 
43
%% Info    -> ets | {ets, Dir} | 
 
44
%%            {dets, Dir} | {dets, Dir, Action} |
 
45
%%            {mnesia, Nodes} | {mnesia, Nodes, Action}
 
46
%% Name    -> atom()
 
47
%% RecName -> Name of the record to store
 
48
%% Attr    -> Attributes of the record stored in the table
 
49
%% Type    -> set | bag
 
50
%% Dir     -> string()
 
51
%% Nodes   -> [node()]
 
52
%% Action  -> keep | clear
 
53
%% 
 
54
%% Open or create a database table. In the mnesia/dets case, 
 
55
%% where the table is stored on disc, it could be of interest
 
56
%% to clear the table. This is controlled by the Action parameter.
 
57
%% An empty node list ([]), is traslated into a list containing
 
58
%% only the own node.
 
59
%% ---------------------------------------------------------------
 
60
open({mnesia,Nodes,clear}, Name, RecName, Attr, Type) when list(Nodes) ->
 
61
    ?vtrace("[mnesia] open ~p database ~p for ~p on ~p; clear",
 
62
            [Type, Name, RecName, Nodes]),
 
63
    mnesia_open(mnesia_table_check(Name), Nodes, RecName, Attr, Type, clear);
 
64
open({mnesia,Nodes,_}, Name, RecName, Attr, Type) ->
 
65
    ?vtrace("[mnesia] open ~p database ~p for ~p on ~p; keep",
 
66
            [Type, Name, RecName, Nodes]),
 
67
    open({mnesia,Nodes}, Name, RecName, Attr, Type);
 
68
open({mnesia,Nodes}, Name, RecName, Attr, Type) when list(Nodes) ->
 
69
    ?vtrace("[mnesia] open ~p database ~p for ~p on ~p",
 
70
            [Type, Name, RecName, Nodes]),
 
71
    mnesia_open(mnesia_table_check(Name), Nodes, RecName, Attr, Type, keep);
 
72
 
 
73
open({dets, Dir, Action}, Name, _RecName, _Attr, Type) ->
 
74
    dets_open(Name, dets_filename(Name, Dir), Type, Action);
 
75
open({dets, Dir}, Name, _RecName, _Attr, Type) ->
 
76
    dets_open(Name, dets_filename(Name, Dir), Type, keep);
 
77
 
 
78
%% This function creates the ets table 
 
79
open(ets, Name, _RecName, _Attr, Type) ->
 
80
    ?vtrace("[ets] open ~p database ~p", [Type, Name]),
 
81
    Ets = ets:new(Name, [Type, protected, {keypos, 2}]),
 
82
    {ets, Ets, undefined};
 
83
open({ets, Dir}, Name, _RecName, _Attr, Type) ->
 
84
    ets_open(Name, Dir, keep, Type);
 
85
open({ets, Dir, Action}, Name, _RecName, _Attr, Type) ->
 
86
    ets_open(Name, Dir, Action, Type).
 
87
 
 
88
ets_open(Name, Dir, keep, Type) ->
 
89
    ?vtrace("[ets] open ~p database ~p", [Type, Name]),
 
90
    File = filename:join(Dir, atom_to_list(Name) ++ ".db"),
 
91
    case file:read_file_info(File) of
 
92
        {ok, _} ->
 
93
            case ets:file2tab(File) of
 
94
                {ok, Tab} ->
 
95
                    {ets, Tab, File};
 
96
                {error, Reason} ->
 
97
                    user_err("failed converting file to (ets-) tab: "
 
98
                             "File: ~p"
 
99
                             "~n~p", [File, Reason]),
 
100
                    Ets = ets:new(Name, [Type, protected, {keypos, 2}]),
 
101
                    {ets, Ets, File}
 
102
            end;
 
103
        {error, _} ->
 
104
            Ets = ets:new(Name, [Type, protected, {keypos, 2}]),
 
105
            {ets, Ets, File}
 
106
    end;
 
107
ets_open(Name, Dir, clear, Type) ->
 
108
    File = filename:join(Dir, atom_to_list(Name) ++ ".db"),
 
109
    Ets  = ets:new(Name, [Type, protected, {keypos, 2}]),
 
110
    {ets, Ets, File}.
 
111
    
 
112
            
 
113
 
 
114
mnesia_open({table_exist,Name},_Nodes,_RecName,_Attr,_Type,clear) ->
 
115
    ?vtrace("[mnesia] database ~p already exists; clear content",[Name]),
 
116
    Pattern = '_',
 
117
    F = fun() -> 
 
118
                Recs = mnesia:match_object(Name,Pattern,read),
 
119
                lists:foreach(fun(Rec) -> 
 
120
                                      mnesia:delete_object(Name,Rec,write)
 
121
                              end, Recs),
 
122
                Recs
 
123
        end,
 
124
    case mnesia:transaction(F) of
 
125
        {aborted,Reason} ->
 
126
            exit({aborted,Reason});
 
127
        {atomic,_} ->
 
128
            {mnesia,Name}
 
129
    end;
 
130
mnesia_open({table_exist,Name},_Nodes,_RecName,_Attr,_Type,keep) ->
 
131
    ?vtrace("[mnesia] database ~p already exists; keep content",[Name]),
 
132
    {mnesia,Name};
 
133
mnesia_open({no_table,Name},[],Type,RecName,Attr,Action) ->
 
134
    mnesia_open({no_table,Name},[node()],Type,RecName,Attr,Action);
 
135
mnesia_open({no_table,Name},Nodes,RecName,Attr,Type,_) ->
 
136
    ?vtrace("[mnesia] no database ~p: create for ~p of type ~p",
 
137
            [Name,RecName,Type]),
 
138
    %% Ok, we assume that this means that the table does not exist
 
139
    Args = [{record_name,RecName}, {attributes,Attr},
 
140
            {type,Type}, {disc_copies,Nodes}],
 
141
    case mnesia:create_table(Name,Args) of
 
142
        {atomic,ok} ->
 
143
            {mnesia,Name};
 
144
        {aborted,Reason} ->
 
145
            %% ?vinfo("[mnesia] aborted: ~p", [Reason]),
 
146
            exit({failed_create_mnesia_table,Reason})
 
147
    end.
 
148
 
 
149
 
 
150
mnesia_table_check(Name) ->
 
151
    ?vtrace("[mnesia] check existens of database ~p",[Name]),
 
152
    case (catch mnesia:table_info(Name,type)) of
 
153
        {'EXIT', _Reason} ->
 
154
            {no_table, Name};
 
155
        _ ->
 
156
            {table_exist, Name}
 
157
    end.
 
158
    
 
159
 
 
160
dets_open(Name, File, Type, Action) ->
 
161
    ?vtrace("[dets] open database ~p (~p)", [Name, Action]),
 
162
    N = dets_open1(Name, File, Type),
 
163
    dets_open2(N, Action).
 
164
 
 
165
dets_open1(Name, File, Type) ->
 
166
    ?vtrace("[dets] open database ~p of type ~p",[Name, Type]),
 
167
    {ok, N} = dets:open_file(Name, [{file, File}, {type, Type}, {keypos, 2}]),
 
168
    N.
 
169
    
 
170
dets_open2(N, clear) ->
 
171
    dets:match_delete(N,'_'),
 
172
    {dets, N};
 
173
dets_open2(N, _) ->
 
174
    {dets, N}.
 
175
 
 
176
%% dets_table_check(Name, Dir) ->
 
177
%%     Filename = dets_filename(Name, Dir),
 
178
%%     ?vtrace("[dets] check existens of database: "
 
179
%%      "~n   ~p -> ~s"
 
180
%%      "~n   ~p"
 
181
%%      "~n   ~p"
 
182
%%      , 
 
183
%%      [Name, Filename, file:list_dir(Dir), file:read_file_info(Filename)]),
 
184
%%     case (catch dets:info(Filename, size)) of
 
185
%%      {'EXIT', Reason} ->
 
186
%%          {no_table, Name, Filename};
 
187
%%      undefined -> %% Introduced in R8
 
188
%%          {no_table, Name, Filename};
 
189
%%      _ ->
 
190
%%          {table_exist, Name, Filename}
 
191
%%     end.
 
192
    
 
193
 
 
194
dets_filename(Name, Dir) ->
 
195
    Dir1 = dets_filename1(Dir),
 
196
    Dir2 = string:strip(Dir1, right, $/),
 
197
    io_lib:format("~s/~p.dat", [Dir2, Name]).
 
198
    
 
199
dets_filename1([])  -> ".";
 
200
dets_filename1(Dir) -> Dir.
 
201
 
 
202
 
 
203
%% ---------------------------------------------------------------
 
204
%% close(DbRef) -> 
 
205
%% DbRef -> term()
 
206
%% 
 
207
%% Close the database. This does nothing in the mnesia case, but
 
208
%% deletes the table in the ets case.
 
209
%% ---------------------------------------------------------------
 
210
close({mnesia,_}) ->
 
211
    ?vtrace("[mnesia] close database: NO ACTION",[]),
 
212
    ok;
 
213
close({dets, Name}) ->
 
214
    ?vtrace("[dets] close database ~p",[Name]),
 
215
    dets:close(Name);
 
216
close({ets, Name, undefined}) ->
 
217
    ?vtrace("[ets] close (delete) table ~p",[Name]),
 
218
    ets:delete(Name);
 
219
close({ets, Name, File}) ->
 
220
    ?vtrace("[ets] close (delete) table ~p",[Name]),
 
221
    write_ets_file(Name, File),
 
222
    ets:delete(Name).
 
223
 
 
224
 
 
225
%% ---------------------------------------------------------------
 
226
%% read(DbRef,Key) -> false | {value,Rec}
 
227
%% DbRef -> term()
 
228
%% Rec   -> tuple()
 
229
%% 
 
230
%% Retrieve a record from the database.
 
231
%% ---------------------------------------------------------------
 
232
read({mnesia, Name}, Key) ->
 
233
    ?vtrace("[mnesia] read (dirty) from database ~p: ~p",[Name,Key]),
 
234
    case (catch mnesia:dirty_read(Name,Key)) of
 
235
        [Rec|_] -> {value,Rec};
 
236
        _ -> false
 
237
    end;
 
238
read({dets, Name}, Key) ->
 
239
    ?vtrace("[dets] read from table ~p: ~p",[Name,Key]),
 
240
    case dets:lookup(Name, Key) of
 
241
        [Rec|_] -> {value, Rec};
 
242
        _ -> false
 
243
    end;
 
244
read({ets, Name, _}, Key) ->
 
245
    ?vtrace("[ets] read from table ~p: ~p",[Name,Key]),
 
246
    case ets:lookup(Name, Key) of
 
247
        [Rec|_] -> {value, Rec};
 
248
        _ -> false
 
249
    end.
 
250
    
 
251
 
 
252
%% ---------------------------------------------------------------
 
253
%% write(DbRef,Rec) -> ok
 
254
%% DbRef -> term()
 
255
%% Rec   -> tuple()
 
256
%% 
 
257
%% Write a record to the database.
 
258
%% ---------------------------------------------------------------
 
259
write({mnesia, Name}, Rec) -> 
 
260
    ?vtrace("[mnesia] write to database ~p",[Name]),
 
261
    F = fun() -> mnesia:write(Name, Rec, write) end,
 
262
    case mnesia:transaction(F) of
 
263
        {aborted, Reason} ->
 
264
            exit({aborted, Reason});
 
265
        {atomic,_} ->
 
266
            ok
 
267
    end;
 
268
write({dets, Name}, Rec) ->
 
269
    ?vtrace("[dets] write to table ~p",[Name]),
 
270
    dets:insert(Name, Rec);
 
271
write({ets, Name, _}, Rec) ->
 
272
    ?vtrace("[ets] write to table ~p",[Name]),
 
273
    ets:insert(Name, Rec).
 
274
 
 
275
 
 
276
%% ---------------------------------------------------------------
 
277
%% delete(DbRef) -> 
 
278
%% DbRef -> term()
 
279
%% 
 
280
%% Delete the database. 
 
281
%% ---------------------------------------------------------------
 
282
delete({mnesia, Name}) ->
 
283
    ?vtrace("[mnesia] delete database: ~p",[Name]),
 
284
    mnesia:delete_table(Name);
 
285
delete({dets, Name}) ->
 
286
    ?vtrace("[dets] delete database ~p",[Name]),
 
287
    File = dets:info(Name, filename),
 
288
    case dets:close(Name) of
 
289
        ok ->
 
290
            file:delete(File);
 
291
        Error ->
 
292
            Error
 
293
    end;
 
294
delete({ets, Name, undefined}) ->
 
295
    ?vtrace("[dets] delete table ~p",[Name]),
 
296
    ets:delete(Name);
 
297
delete({ets, Name, File}) ->
 
298
    ?vtrace("[dets] delete table ~p",[Name]),
 
299
    file:delete(File),
 
300
    ets:delete(Name).
 
301
 
 
302
 
 
303
%% ---------------------------------------------------------------
 
304
%% delete(DbRef, Key) -> ok
 
305
%% DbRef -> term()
 
306
%% Key   -> term()
 
307
%% 
 
308
%% Delete a record from the database.
 
309
%% ---------------------------------------------------------------
 
310
delete({mnesia, Name}, Key) -> 
 
311
    ?vtrace("[mnesia] delete from database ~p: ~p", [Name, Key]),
 
312
    F = fun() -> mnesia:delete(Name, Key, write) end,
 
313
    case mnesia:transaction(F) of
 
314
        {aborted,Reason} ->
 
315
            exit({aborted,Reason});
 
316
        {atomic,_} ->
 
317
            ok
 
318
    end;
 
319
delete({dets, Name}, Key) ->
 
320
    ?vtrace("[dets] delete from table ~p: ~p", [Name, Key]),
 
321
    dets:delete(Name, Key);
 
322
delete({ets, Name, _}, Key) ->
 
323
    ?vtrace("[ets] delete from table ~p: ~p", [Name, Key]),
 
324
    ets:delete(Name, Key).
 
325
 
 
326
 
 
327
%% ---------------------------------------------------------------
 
328
%% match_object(DbRef,Pattern) -> [tuple()]
 
329
%% DbRef -> term()
 
330
%% Pattern -> tuple()
 
331
%% 
 
332
%% Search the database for records witch matches the pattern.
 
333
%% ---------------------------------------------------------------
 
334
match_object({mnesia, Name}, Pattern) ->
 
335
    ?vtrace("[mnesia] match_object in ~p of ~p",[Name, Pattern]),
 
336
    F = fun() -> mnesia:match_object(Name, Pattern, read) end,
 
337
    case mnesia:transaction(F) of
 
338
        {aborted, Reason} ->
 
339
            exit({aborted, Reason});
 
340
         {atomic, Recs} ->
 
341
            Recs
 
342
    end;
 
343
match_object({dets, Name}, Pattern) ->
 
344
    ?vtrace("[dets] match_object in ~p of ~p",[Name, Pattern]),
 
345
    dets:match_object(Name, Pattern);
 
346
match_object({ets, Name, _}, Pattern) ->
 
347
    ?vtrace("[ets] match_object in ~p of ~p",[Name, Pattern]),
 
348
    ets:match_object(Name, Pattern).
 
349
    
 
350
 
 
351
%% ---------------------------------------------------------------
 
352
%% match_delete(DbRef,Pattern) -> 
 
353
%% DbRef -> term()
 
354
%% Pattern -> tuple()
 
355
%% 
 
356
%% Search the database for records witch matches the pattern and 
 
357
%% deletes them from the database.
 
358
%% ---------------------------------------------------------------
 
359
match_delete({mnesia, Name}, Pattern) -> 
 
360
    ?vtrace("[mnesia] match_delete in ~p with pattern ~p",[Name,Pattern]),
 
361
    F = fun() -> 
 
362
                Recs = mnesia:match_object(Name, Pattern, read),
 
363
                lists:foreach(fun(Rec) -> 
 
364
                                      mnesia:delete_object(Name, Rec, write)
 
365
                              end, Recs),
 
366
                Recs
 
367
        end,
 
368
    case mnesia:transaction(F) of
 
369
        {aborted, Reason} ->
 
370
            exit({aborted, Reason});
 
371
        {atomic,R} ->
 
372
            R
 
373
    end;
 
374
match_delete({dets, Name}, Pattern) -> 
 
375
    ?vtrace("[dets] match_delete in ~p with pattern ~p",[Name,Pattern]),
 
376
    Recs = dets:match_object(Name, Pattern),
 
377
    dets:match_delete(Name, Pattern),
 
378
    Recs;
 
379
match_delete({ets, Name, _}, Pattern) -> 
 
380
    ?vtrace("[ets] match_delete in ~p with pattern ~p",[Name,Pattern]),
 
381
    Recs = ets:match_object(Name, Pattern),
 
382
    ets:match_delete(Name, Pattern),
 
383
    Recs.
 
384
 
 
385
 
 
386
%% ---------------------------------------------------------------
 
387
%% tab2list(DbRef) -> [tuple()]
 
388
%% DbRef -> term()
 
389
%% 
 
390
%% Return all records in the table in the form of a list.
 
391
%% ---------------------------------------------------------------
 
392
tab2list({mnesia, Name}) ->
 
393
    ?vtrace("[mnesia] tab2list -> list of ~p", [Name]),
 
394
    match_object({mnesia, Name}, mnesia:table_info(Name, wild_pattern));
 
395
tab2list({dets, Name}) ->
 
396
    ?vtrace("[dets] tab2list -> list of ~p", [Name]),
 
397
    match_object({dets, Name}, '_');
 
398
tab2list({ets, Name, _}) ->
 
399
    ?vtrace("[ets] tab2list -> list of ~p", [Name]),
 
400
    ets:tab2list(Name).
 
401
 
 
402
 
 
403
 
 
404
%% ---------------------------------------------------------------
 
405
%% info(Db) -> taglist()
 
406
%% info(Db, Item) -> Info
 
407
%% Db   -> term()
 
408
%% Item -> atom()
 
409
%% tablist() -> [{key(),value()}]
 
410
%% key() -> atom()
 
411
%% value() -> term()
 
412
%% 
 
413
%% Retrieve table information.
 
414
%% ---------------------------------------------------------------
 
415
info({mnesia, Name}) ->
 
416
    case (catch mnesia:table_info(Name, all)) of
 
417
        Info when list(Info) ->
 
418
            Info;
 
419
        {'EXIT', {aborted, Reason}} ->
 
420
            {error, Reason};
 
421
        Else ->
 
422
            {error, Else}
 
423
    end;
 
424
info({dets, Name}) ->
 
425
    dets:info(Name);
 
426
info({ets, Name, _}) ->
 
427
    case ets:info(Name) of
 
428
        T when tuple(T) ->
 
429
            tuple_to_list(T);
 
430
        L ->
 
431
            L
 
432
    end.
 
433
 
 
434
 
 
435
info({mnesia, Name}, Item) ->
 
436
    case (catch mnesia:table_info(Name, Item)) of
 
437
        {'EXIT', {aborted, Reason}} ->
 
438
            {error, Reason};
 
439
        Info ->
 
440
            Info
 
441
    end;
 
442
info({dets, Name}, memory) ->
 
443
    dets:info(Name, file_size);
 
444
info({dets, Name}, Item) ->
 
445
    dets:info(Name, Item);
 
446
info({ets, Name, _}, Item) ->
 
447
    ets:info(Name, Item).
 
448
 
 
449
 
 
450
%% ---------------------------------------------------------------
 
451
%% sync(Db) -> ok | {error, Reason}
 
452
%% Db     -> term()
 
453
%% Reason -> term()
 
454
%% 
 
455
%% Dump table to disc (if possible)
 
456
%% ---------------------------------------------------------------
 
457
 
 
458
sync({mnesia, _}) ->
 
459
    ok;
 
460
sync({dets, Name}) ->
 
461
    dets:sync(Name);
 
462
sync({ets, _Name, undefined}) ->
 
463
    ok;
 
464
sync({ets, Name, File}) ->
 
465
    write_ets_file(Name, File).
 
466
 
 
467
 
 
468
%% ---------------------------------------------------------------
 
469
%% backup(Db, BackupDir) -> ok | {error, Reason}
 
470
%% Db     -> term()
 
471
%% Reason -> term()
 
472
%% 
 
473
%% Make a backup copy of the DB (only valid for det and ets)
 
474
%% ---------------------------------------------------------------
 
475
 
 
476
backup({mnesia, _}, _) ->
 
477
    ok;
 
478
backup({dets, Name}, BackupDir) ->
 
479
    case dets:info(Name, filename) of
 
480
        undefined ->
 
481
            {error, no_file};
 
482
        Filename ->
 
483
            case filename:dirname(Filename) of
 
484
                BackupDir ->
 
485
                    {error, db_dir};
 
486
                _ ->
 
487
                    Type = dets:info(Name, type),
 
488
                    KP   = dets:info(Name, keypos),
 
489
                    dets_backup(Name, 
 
490
                                filename:basename(Filename), 
 
491
                                BackupDir, Type, KP)
 
492
            end
 
493
    end;
 
494
backup({ets, _Name, undefined}, _BackupDir) ->
 
495
    ok;
 
496
backup({ets, Name, File}, BackupDir) ->
 
497
    Filename = filename:basename(File),
 
498
    case filename:join(BackupDir, Filename) of
 
499
        File ->
 
500
            %% Oups: backup-dir and db-dir the same
 
501
            {error, db_dir};
 
502
        BackupFile ->
 
503
            write_ets_file(Name, BackupFile)
 
504
    end.
 
505
 
 
506
              
 
507
dets_backup(Name, Filename, BackupDir, Type, KP) ->
 
508
    ?vtrace("dets_backup -> entry with"
 
509
            "~n   Name:      ~p"
 
510
            "~n   Filename:  ~p"
 
511
            "~n   BackupDir: ~p"
 
512
            "~n   Type:      ~p"
 
513
            "~n   KP:        ~p", [Name, Filename, BackupDir, Type, KP]),
 
514
    BackupFile = filename:join(BackupDir, Filename),
 
515
    ?vtrace("dets_backup -> "
 
516
            "~n   BackupFile: ~p", [BackupFile]),
 
517
    Backup = list_to_atom(atom_to_list(Name) ++ "_backup"),
 
518
    Opts   = [{file, BackupFile}, {type, Type}, {keypos, KP}], 
 
519
    case dets:open_file(Backup, Opts) of
 
520
        {ok, B} ->
 
521
            ?vtrace("dets_backup -> create fun", []),
 
522
            F = fun(Arg) -> 
 
523
                        dets_backup(Arg, start, Name, B)
 
524
                end,
 
525
            dets:safe_fixtable(Name, true),
 
526
            Res = dets:init_table(Backup, F, [{format, bchunk}]),
 
527
            dets:safe_fixtable(Name, false),
 
528
            ?vtrace("dets_backup -> Res: ~p", [Res]),
 
529
            Res;
 
530
        Error ->
 
531
            ?vinfo("dets_backup -> open_file failed: "
 
532
                   "~n   ~p", [Error]),
 
533
            Error
 
534
    end.
 
535
 
 
536
 
 
537
dets_backup(close, _Cont, _Name, B) ->
 
538
    dets:close(B),
 
539
    ok;
 
540
dets_backup(read, Cont1, Name, B) ->
 
541
    case dets:bchunk(Name, Cont1) of
 
542
        {Cont2, Data} ->
 
543
            F = fun(Arg) ->
 
544
                        dets_backup(Arg, Cont2, Name, B)
 
545
                end,
 
546
            {Data, F};
 
547
        '$end_of_table' ->
 
548
            dets:close(B),
 
549
            end_of_input;
 
550
        Error ->
 
551
            Error
 
552
    end.
 
553
 
 
554
 
 
555
%%----------------------------------------------------------------------
 
556
 
 
557
write_ets_file(Name, File) ->
 
558
    TmpFile = File ++ ".tmp",
 
559
    case ets:tab2file(Name, TmpFile) of
 
560
        ok ->
 
561
            case file:rename(TmpFile, File) of
 
562
                ok ->
 
563
                    ok;
 
564
                Else ->
 
565
                    user_err("Warning: could not move file ~p"
 
566
                             " (~p)", [File, Else])
 
567
            end;
 
568
        {error, Reason} ->
 
569
            user_err("Warning: could not save file ~p (~p)",
 
570
                     [File, Reason])
 
571
    end.
 
572
 
 
573
 
 
574
%%----------------------------------------------------------------------
 
575
 
 
576
user_err(F, A) ->
 
577
    snmpa_error:user_err(F, A).