/// <summary> /// Closes the journal file. /// </summary> internal void Close() { lock (this) { if (!is_open) { throw new IOException("Journal file is already closed."); } data.Close(); data = null; is_open = false; } }
/// <summary> /// Opens the journal for recovery. /// </summary> /// <remarks> /// This scans the journal and generates some statistics about the journal file /// such as the last check point and the journal number. /// </remarks> /// <returns></returns> /// <exception cref="IOException"> /// If the journal file doesn't exist. /// </exception> internal JournalSummary OpenForRecovery() { if (is_open) { throw new IOException("Journal file is already open."); } if (!File.Exists(file)) { throw new IOException("Journal file does not exists."); } // Open the random access file to this journal data = new StreamFile(file, read_only ? FileAccess.Read : FileAccess.ReadWrite); is_open = true; // Create the summary object (by default, not recoverable). JournalSummary summary = new JournalSummary(this); long end_pointer = data.Length; // If end_pointer < 8 then can't recovert this journal if (end_pointer < 8) { return summary; } // The input stream. BinaryReader din = new BinaryReader(data.FileStream, Encoding.Unicode); try { // Set the journal number for this this.journal_number = din.ReadInt64(); long position = 8; ArrayList checkpoint_res_list = new ArrayList(); // Start scan while (true) { // If we can't Read 12 bytes ahead, return the summary if (position + 12 > end_pointer) { return summary; } long type = din.ReadInt64(); int size = din.ReadInt32(); // Console.Out.WriteLine("Scan: " + type + " pos=" + position + " size=" + size); position = position + size + 12; bool skip_body = true; // If checkpoint reached then we are recoverable if (type == 100) { summary.last_checkpoint = position; summary.can_be_recovered = true; // Add the resources input this check point summary.resource_list.AddRange(checkpoint_res_list); // And clear the temporary list. checkpoint_res_list.Clear(); } // If end reached, or type is not understood then return else if (position >= end_pointer || type < 1 || type > 32) { return summary; } // If we are resource type, then load the resource if (type == 2) { // We don't skip body for this type, we Read the content skip_body = false; long id = din.ReadInt64(); int str_len = din.ReadInt32(); StringBuilder str = new StringBuilder(str_len); for (int i = 0; i < str_len; ++i) { str.Append(din.ReadChar()); } String resource_name = str.ToString(); checkpoint_res_list.Add(resource_name); } if (skip_body) din.BaseStream.Seek(size, SeekOrigin.Current); } } finally { din.Close(); } }
public SFFileStream(StreamFile file) { this.file = file; }
/// <summary> /// Opens the journal file. /// </summary> /// <param name="journal_number"></param> /// <exception cref="IOException"> /// If the journal file exists. /// </exception> internal void Open(long journal_number) { if (is_open) { throw new IOException("Journal file is already open."); } if (File.Exists(file)) { throw new IOException("Journal file already exists."); } this.journal_number = journal_number; data = new StreamFile(file, read_only ? FileAccess.Read : FileAccess.ReadWrite); data_out = new BinaryWriter(new BufferedStream(data.FileStream), Encoding.Unicode); data_out.Write(journal_number); is_open = true; }